LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

array pointer from dll

Please help me with a array pointer from a dll. I am trying to use an API to read data from a file that is generated by a data acquisition instrument.

The vendor provided the API and I am adapting to LV 2009 using call library functions to interface the dll. The dll uses parameters from a struct, explained in the spec docs, to return values from a file.

--------------

struct WdfAccessParam { //meaning usable value

 

UINT version; //version information 0 (fixed value)

UINT ch; //reading channel 0–

UINT block; //reading block 0–

INT start; //reading start point 0–

INT count; //reading count 1–

INT ppRate; //data compression rate 0x200 (raw data)

INT waveType; //type of output waveform ADWave

INT dataType; //data type of output waveform SHORT_TYP

INT cntOut; //output count No. of successfully read points

void* dst; //pointer to an output buffer Waveform data

INT box; //box mode ;0:Auto Box numbers used (0:main)

INT rsv1; //reserved 0 (fixed value)

INT rsv2; //reserved 0 (fixed value)

INT rsv3; //reserved 0 (fixed value)

INT rsv4; //reserved 0 (fixed value)

INT rsv5; //reserved 0 (fixed value)

};

---------------------

I am having problems with this data output pointer

void* dst; //pointer to an output buffer Waveform data

 

There is a VC6 example that will return data. It uses a smaller set of the struct

-------------------------

wdfAccParam[0].block = nBlockNumber - 1 ; // from file header

wdfAccParam[0].count = nBlockSize[0] ; // from file header

 wdfAccParam[0].ppRate = 512 ; // constant from the working VC6 example                                              

wdfAccParam[0].waveType = 0 ;  // 0(AD) or 1(Physical) or 2(Scaling)

wdfAccParam[0].dataType = nDataType[0] ; // constant from the working VC6 example

wdfAccParam[0].dst = new short[nBlockSize[0]] ;// this is the problem, I am not sure how to work with this cannot get the correct data as a return

---------------------

The VC6 example is attached. It will return a sine wave array from the data file. I build a LV cluster for the wdfAccParam struct inputs to the call library WdfGetScaleWave function. It seems to execute without any error, but the  ret = WdfGetScaleWave(hHandle, &wdfAccParam[0]) ; // Get AD Data  part I am having trouble getting/dereferencing the data.

This is probably insufficient information but please let me know what more information I can provide.

thanks
jim

Download All
0 Kudos
Message 1 of 36
(6,585 Views)

I doubt that this can be done using just LV (Maybe there's a guru somewhere who knows how to do it 🙂

Probably the best would be to create a helper DLL that provides functions to allocate and read the data in LV.

0 Kudos
Message 2 of 36
(6,573 Views)

Could you post the DLL as well? Also, if you are getting any specific error messages, could you post those as well?

Tanya Visser
National Instruments
LabVIEW Group Manager
0 Kudos
Message 3 of 36
(6,561 Views)

Define dst as a UINT32 (assuming a 32 bit program) instead of an array. Then use a call to memcpy with the CLN (msvcrt.dll, C calling convention) with dest to set a labview UNIT8 array (with an empty array of unit8 as the input), src set to a by value 32 UINT (with dst as the input), count to the number of elements in the array times the size in bytes of a single element (this depends on what dst is suposed to hold, if it's doubles then you need to multiply by 8, shorts 2, ints 4). To make sure the array input is big enough set the minumsize (in the CLN) for the array input to the count parameter of memcpy. Then use a Type Cast to convert the output array of UINT8 to an array of your datatype.

 

Make sure the minumsize input is set (other wise you're overwriting things you don't want to). Also make sure you have the call conventions set properly (LabVIEW will usually crash if you mess this up). Also check how releasing memory is supposed to be handled, since if you need to (by calling another CLN) and don't you have a memory leak, if the dll does then you could be copying invalid data (another call to the api may invalidate the dst pointer among other possibilities).

 

Note: Messing with raw pointers is an easy way to crash your program and LabVIEW, if you get something wrong.

0 Kudos
Message 4 of 36
(6,549 Views)

There are some hidden functions inside the LabVIEW.exe and the lvrt.dll that allow you to mess around with pointers. In the CNL, type in LabVIEW, this automatically redirects you to the lvrt.dll when you build an application. These functions are completly undocumented, but ther is a header file (search for LabVIEW.h and lvrt.h). The only person that can do something useful with this stuff is RolfK, so it is worth to browse his posts in the forum if he isn't responding within the next days.

About everything else I think Matt W is a good guidance, expecially in the warning about crashes.

 

Felix

0 Kudos
Message 5 of 36
(6,535 Views)

Thanks, Folks  for all the suggestions. I will work through them along with my C++ helper. Tanya, I feel I should be careful with posting the dll as it was provided with a distribution license. Andy H may have an alternate method.

Jim H

0 Kudos
Message 6 of 36
(6,505 Views)

Hi Jim,

 

Regarding your message, I understand your hesitance to post the dll on the forum, but we unfortunately do not directly accept third party dlls or software for troubleshooting. I suggest that you try the methods offered by the users here on the forum, and see if those solve your problem.

 

Also, you could try consulting this manual:

http://digital.ni.com/manuals.nsf/websearch/8D930295FFBF9F7686256D2C00624728

Andy H.
National Instruments
0 Kudos
Message 7 of 36
(6,481 Views)

 


@matt W wrote:

Define dst as a UINT32 (assuming a 32 bit program) instead of an array. Then use a call to memcpy with the CLN (msvcrt.dll, C calling convention) with dest to set a labview UNIT8 array (with an empty array of unit8 as the input), src set to a by value 32 UINT (with dst as the input), count to the number of elements in the array times the size in bytes of a single element (this depends on what dst is suposed to hold, if it's doubles then you need to multiply by 8, shorts 2, ints 4). To make sure the array input is big enough set the minumsize (in the CLN) for the array input to the count parameter of memcpy. Then use a Type Cast to convert the output array of UINT8 to an array of your datatype.


Instead of using memcpy, a better choice is to use the built-in LabVIEW function MoveBlock.  You can find documentation for it in the LabVIEW help; also look in the help under Memory Manager.  You call it through a Call Library Node with library name set to "LabVIEW".

 

Message 8 of 36
(6,476 Views)

I changed dst in the input cluster to be a scalar U32. The problem I seem to be having now is in the output cluster dst will not change value from zero to any other number that would represent a real memory pointer location.

0 Kudos
Message 9 of 36
(6,473 Views)

It looks like the library expects you to pre-allocate space and provide a pointer to it.  This gets a bit more complicated, but you can use the Memory Manager function DSNewPtr (again, Call Library Node with the library name set to LabVIEW) to allocate memory and return a pointer to it.  Bundle the pointer value into the cluster before calling the library function.  After the library call completes, use MoveBlock to get the data from the pointer, then use DSDisposePtr to release the memory.

0 Kudos
Message 10 of 36
(6,466 Views)