How to link MacOS frameworks in mex?

2 views (last 30 days)
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)

Accepted Answer

Tim Meehan
Tim Meehan on 31 Jan 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;
}

More Answers (1)

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

Categories

Find more on Write C Functions Callable from MATLAB (MEX Files) in Help Center and File Exchange

Community Treasure Hunt

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

Start Hunting!