How to link MacOS frameworks in mex?

2 ビュー (過去 30 日間)
Tim Meehan
Tim Meehan 2019 年 1 月 31 日
回答済み: Sean Kenny 2020 年 4 月 21 日
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)

採用された回答

Tim Meehan
Tim Meehan 2019 年 1 月 31 日
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;
}

その他の回答 (1 件)

Sean Kenny
Sean Kenny 2020 年 4 月 21 日
I guess I'm the other person in the universe... Works great! Thanks for posting this solution.

カテゴリ

Help Center および File ExchangeWrite C Functions Callable from MATLAB (MEX Files) についてさらに検索

タグ

Community Treasure Hunt

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

Start Hunting!

Translated by