Problem with a pointer to a (array of) structure(s) when calling a DLL

6 views (last 30 days)
Hi,
I am calling a function called “niScope_Read”[1] in a library called “niscope_32.dll”[2] in MATLAB and I have a problem with a pointer of a (array of) structure(s). This DLL controls a multi-channel DAQ from National Instruments and there is no MATLAB API! My code (see below) works fine when I retrieve data from a single channel because creating an structure and its pointer is easy using libstruct() and libpointer(). However, when I try to retrieve data from more than 1 channel, MATLAB crashes!!! and I suspect is because of memory access violation.
%===== MATLAB CODE =====
channelListPtr=libpointer('voidPtr',[uint8('3') 0]); %e.g. '3' or '4-5'
numWfms= 1; %this should correspond with the number of channels
LenWfm = 1000;
wfmsPtr=libpointer('doublePtr',zeros(1,numWfms*LenWfm));
wfmsInfoX.absoluteInitialX = double(0);
wfmsInfoX.relativeInitialX = double(0);
wfmsInfoX.xIncrement = double(0);
wfmsInfoX.actualSamples = zeros(1,'int32');
wfmsInfoX.offset = double(0);
wfmsInfoX.gain = double(0);
wfmsInfoX.reserved1 = double(0);
wfmsInfoX.reserved2 = double(0);
wfmsInfo = libstruct('niScope_wfmInfo', wfmsInfoX); %<- CHECK HERE
wfmsInfoPtr= libpointer('niScope_wfmInfoPtr', wfmsInfo); %<- CHECK HERE
status =calllib('niscope_32','niScope_Read',devHandle,channelListPtr,1,LenWfm,wfmsPtr,wfmsInfoPtr);
wfms = get(wfmsPtr,'Value');
wfmsInfo = get(wfmsInfoPtr,'Value');
%=======================
Basically, an array (with “numWfms” elements) of structures (of type “'niScope_wfmInfo”) must be created first and the pointer to the first element should be passed to the function. The DLL will write data on the structure for each channel (that’s why it is an array). In C(++) this code should do (according to National Instruments) the following:
%===== C(++) code =====
wfmInfoPtr = malloc (sizeof (struct niScope_wfmInfo) * numWfms);
%======================
So, how can I implement this in MATLAB? I’ve tried already several things without success such as:
%===== MATLAB CODE =====
wfmsInfo = libstruct('niScope_wfmInfo', wfmsInfoX);
wfmsInfoArray(1:numWfms)= wfmsInfo; %<- DOES NOT WORK
wfmsInfoPtr= libpointer('niScope_wfmInfoPtr', wfmsInfo);
%=======================
Could anyone help here please?
Regards, David A.

Answers (1)

Philip Borghesani
Philip Borghesani on 28 Mar 2013
No guarantees here because support for arrays of structs is limited and only works in recent versions of MATLAB. The way to allocate an array of structs is to let libstruct do it for you. initialize wfmsInfoX as an array of structures for example:
wfmsInfoX(1).absoluteInitialX = 0;
wfmsInfoX(2).absoluteInitialX = 0;
wfmsInfo = libstruct('niScope_wfmInfo', wfmsInfoX);
There is no need to initialize all values only those that are not 0 and at least one field must be initialized. There should be no need for wfmsInfoPtr you should be able to pass wfmsInfo directly as a pointer.
If you are using an older version of MATLAB or receive other errors then I suggest creating a helper dll to build the structure or mex file to do the entire operation.
  3 Comments
Philip Borghesani
Philip Borghesani on 2 Apr 2013
After the call you should be able to do:
ptr=libPointer('niScope_wfmInfoPtr', wfmsInfo) % I think this can be before or after the call.
secondChannelPtr=ptr+1; %repeat for all channels
secondChannelPtr.value % or use get
Martin Reiche
Martin Reiche on 18 Mar 2021
Hello Philip
I implemented the same workaround you proposed reading data from a frame grabber with a dll.
But on the final step when incrementing the pointer in order to step through the struct array this is not accepted by Matlab for the c_type I have to use. Do you have any idea?
Thanks in forward for any help
What I have done:
VcDtInfoPtr=libpointer; % Type NULL
VcDtInfo.hw_time=uint64(0); %hardware time stamp (unit = 1s/40e6) VcDtInfo.vc_dt=uint32(0); %VirtualChannel/DataType combination ....etc, the same struct as C-type "VcDtInfo" is defined in the dll-header
app.Array_VcDtInfo=repmat(VcDtInfo,256,1); %array of structs
app.VcDtInfoPtr=libstruct('VcDtInfo',app.Array_VcDtInfo); %Pointer to start of struct array
[h,app.vc_Anzahl,app.Array_VcDtInfo]=calllib('s_dll','get_locked_buffer_info',app.card_No,app.channel_No,app.vc_Anzahl,app.VcDtInfoPtr,info_size);
struct_no1=get(app.VcDtInfoPtr)% I get expected struct
pointer2= app.VcDtInfoPtr+1 % or pointer2=plus(app.VcDtInfoPtr,1)
Undefined operator '+' for input arguments of type 'lib.VcDtInfo'
P.S. the function get_locked_bufferinfo only accepts teh struct_type as input and not a simple field of bytes, where teh incrementation would work for my understanding.

Sign in to comment.

Categories

Find more on Instrument Control Toolbox Supported Hardware 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!