How to link MacOS frameworks in mex?

2 visualizzazioni (ultimi 30 giorni)
Tim Meehan
Tim Meehan il 31 Gen 2019
Risposto: Sean Kenny il 21 Apr 2020
I'm trying to write a test program to list the instruments attached to my computer using the NI-VISA libraries on MacOS. It seems that I can't get the mex file to link with the VISA framework. Has anyone had any luck linking to the NI-VISA framework in MacOS?
Test program (visa_enumerate.c):
#include "mex.h"
#include "matrix.h"
#include "visa.h"
#define BUFFER_SIZE 2048
mxArray* enumerateInstruments()
{
ViSession defaultRM;
ViSession instr;
ViStatus status;
ViChar buffer[BUFFER_SIZE];
ViUInt32 device_count;
ViFindList flist;
viOpenDefaultRM(&defaultRM);
viFindRsrc(defaultRM, (ViString)"?*INSTR", &flist, &device_count, buffer);
char* fieldnames[3]= {"ResourceName", "Alias", "Identification"};
mxArray *deviceList = mxCreateStructMatrix(device_count, 3, 3, (const char**)fieldnames);
while (device_count--)
{
status = viOpen(defaultRM, buffer, VI_NULL, 3000, &instr);
if (status == VI_SUCCESS)
{
status = viGetAttribute(instr, VI_ATTR_RSRC_NAME, buffer);
if (status == VI_SUCCESS)
mxSetField(deviceList, device_count, "ResourceName", mxCreateString(buffer));
status = viParseRsrcEx(defaultRM, buffer, VI_NULL, VI_NULL, VI_NULL, VI_NULL, buffer);
if (status == VI_SUCCESS)
mxSetField(deviceList, device_count, "Alias", mxCreateString(buffer));
status = viQueryf(instr, (ViString)"*IDN?\n", (ViString)"%t", buffer);
if (status == VI_SUCCESS)
mxSetField(deviceList, device_count, "Identification", mxCreateString(buffer));
}
viClose(instr);
viFindNext(flist, buffer);
}
viClose(flist);
viClose(defaultRM);
return deviceList;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mxArray *data = enumerateInstruments();
plhs[0] = data;
return;
}
Build script:
#!/bin/sh
MATLAB=/Applications/MATLAB_R2018b.app
MEX=$MATLAB/bin/maci64/mex
MEX_FLAGS="-v -largeArrayDims"
VISA_HEADERS=/Library/Frameworks/VISA.framework/Headers
VISA_LIBRARIES=/Library/Frameworks/VISA.framework
$MEX $MEX_FLAGS -I$VISA_HEADERS -L$VISA_LIBRARIES visa_enumerate.c
Errors:
Undefined symbols for architecture x86_64:
"_viClose", referenced from:
_enumerateInstruments in visa_enumerate.o
"_viFindNext", referenced from:
_enumerateInstruments in visa_enumerate.o
"_viFindRsrc", referenced from:
_enumerateInstruments in visa_enumerate.o
"_viGetAttribute", referenced from:
_enumerateInstruments in visa_enumerate.o
"_viOpen", referenced from:
_enumerateInstruments in visa_enumerate.o
"_viOpenDefaultRM", referenced from:
_enumerateInstruments in visa_enumerate.o
"_viParseRsrcEx", referenced from:
_enumerateInstruments in visa_enumerate.o
"_viQueryf", referenced from:
_enumerateInstruments in visa_enumerate.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Risposta accettata

Tim Meehan
Tim Meehan il 31 Gen 2019
I figured it out. I'm posting this in case the one other person in the universe that wants to do this can find it useful.
First, an ugly hack to get mex to find the VISA framework: I made a symbolic link in the directory that I am building the mex file in:
ln -s /Library/Frameworks/VISA.framework/VISA libVISA.dylib
Afterwards, I modified my build script:
#!/bin/sh
MATLAB=/Applications/MATLAB_R2018b.app
MEX=$MATLAB/bin/maci64/mex
MEX_FLAGS="-v -largeArrayDims"
VISA_HEADERS=/Library/Frameworks/VISA.framework/Headers
# VISA_LIBRARIES=/Library/Frameworks/VISA.framework
$MEX $MEX_FLAGS -I$VISA_HEADERS -L. -lVISA visa_enumerate.c
Then, fixed some of the issues in the test code:
#include "mex.h"
#include "matrix.h"
#include "visa.h"
#include <string.h>
#include "ctype.h"
#define BUFFER_SIZE 256
mxArray* enumerateInstruments()
{
ViSession defaultRM;
ViSession instr;
ViStatus status;
ViChar buffer[BUFFER_SIZE];
ViUInt32 device_count;
ViFindList flist;
viOpenDefaultRM(&defaultRM);
viFindRsrc(defaultRM, (ViString)"?*INSTR", &flist, &device_count, buffer);
char* fieldnames[3]= {"ResourceName", "Alias", "Identification"};
mxArray *deviceList = mxCreateStructMatrix(device_count, 1, 3, (const char**)fieldnames);
while (device_count--)
{
status = viOpen(defaultRM, buffer, VI_NULL, 3000, &instr);
if (status == VI_SUCCESS)
{
status = viGetAttribute(instr, VI_ATTR_RSRC_NAME, buffer);
if (status == VI_SUCCESS)
{
mxSetField(deviceList, device_count, "ResourceName", mxCreateString(buffer));
}
ViUInt16 intfType;
ViUInt16 intfNumber;
ViChar alias[BUFFER_SIZE];
status = viParseRsrcEx(defaultRM, buffer, &intfType, &intfNumber, VI_NULL, VI_NULL, alias);
if (status == VI_SUCCESS)
{
mxSetField(deviceList, device_count, "Alias", mxCreateString(alias));
}
status = viQueryf(instr, (ViString)"*IDN?\n", (ViString)"%t", buffer);
if (status == VI_SUCCESS)
{
// Remove trailing whitespace.
char *end = buffer + strlen(buffer) - 1;
while (end > buffer && isspace((unsigned char) *end))
{
*end = '\0';
end--;
}
mxSetField(deviceList, device_count, "Identification", mxCreateString(buffer));
}
}
viClose(instr);
viFindNext(flist, buffer);
}
viClose(flist);
viClose(defaultRM);
return deviceList;
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
mxArray *data = enumerateInstruments();
plhs[0] = data;
return;
}

Più risposte (1)

Sean Kenny
Sean Kenny il 21 Apr 2020
I guess I'm the other person in the universe... Works great! Thanks for posting this solution.

Categorie

Scopri di più su Write C Functions Callable from MATLAB (MEX Files) in Help Center e File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by