LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Call library function node with array of clusters using array data pointer

Solved!
Go to solution

@rolfk wrote:

Now you lost me!

 



 

You can't have code in your function that treats the incoming array in two different ways at the same time. The array is either a LabVIEW data handle or an array data pointer and trying to treat it in a different way than what you passed into it will surely cause strange effects including possible Access Violations.

 

I'm not planning to have both sets of code.  I want to use it as an array data pointer.  It wasn't working, so I tried accessing it as a LabVIEW data handle to see what I would get, just as an experiment.  To my surprise, it worked all the time, no matter what settings I picked.

 

I thought that "array data pointer" would give me the data array without the dimSize.  Since the knowledge base article suggested attaching a CIN and generating code I did that and copy and pasted it into our DLL in a debugging version.  All that stuff is just test code to try to figure out what is going on.

 

And that is what my example shows to happen!

 

But it does not happen in my case.

 

 

OK, I see I wrote the answers backwards about these two bits of code.  That is probably why I lost you!  I will look at these two pieces of code again, and write the correct answers.

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

	fprintf(pFile, "OK, using CIN generated structures: dimSize %d, with the following data: \n", pTD->dimSize);
	for (i = 0; i < numWords; i++) {
		fprintf(pFile, "%d: control--0x%x, data--0x%x \n", i, pTD->data[i].control, pTD->data[i].data);
	}
	fflush(pFile);

 

THIS produces valid data in the log file.  (It shouldn't ?)

 

But does this part produce valid data in the log file? (it should)

	pFile = fopen("LoadFIFOLog.txt", "w");
	fprintf(pFile, "Starting Load FIFO with %d data words, data pointer 0x%x, with the following data&colon; \n", numWords, data);
	for (i = 0; i < numWords; i++) {
		fprintf(pFile, "%d: control--0x%x, data--0x%x \n", i, data[i].control, data[i].data);
	}
	fflush(pFile);

 

THIS is the one that DOES NOT WORK.  It gives me garbage.

 

You say that the first part I quoted does not work (which uses the LabVIEW data handle format) and the second always works irrespective of the configuration you use for the array parameter in the Call Library.

 

As I explained, I answered backwards before.  Now I fixed it.

 

I suspect some mess up on your part. You can't have those two codes inside at the same time. Either you configure the parameter as array data pointer and use the code from my second quote (the first logging part in your source) or you configure it as array data handle and use the code in my first quoted source code (your second part in the logging). You can't have both active at the same time or you will at least access invalid memory if not worse and that could cause all kind of strange effects, including you seeing each time a valid logging and some garbage but the first time the first logging part creates the valid code and the second time the second one does.

 

OK, I don't plan to have them both.  All the stuff in between TEMP and END TEMP comments is going away.  That code is my attempt to figure out what is going on.

 

 


 

You could declare your wrapper as const. Passing a const to a non-const declared value is valid, the opposite not.

 

I think this time you got it backwards.  You can pass a non-const variable into a function with a const parameter, but not the other way around.

 

Of course it doesn't really buy you anything as the underlaying DLL developer could still decide he wants to update the data in the array at some point and LabVIEW believing it is safe to reuse the array elsewhere could then be tripped by this as it might suddenly use the modified array, believing it should be still the original array as when it got passed to your CLN.


 

 

 


 

 

 


 

0 Kudos
Message 11 of 21
(2,341 Views)

Would this work differently in LabVIEW and LabVIEW Realtime?  We use the same VIs for both (most of the VIs in our library).

I am currently running it on LabVIEW RT.

 

Batya

0 Kudos
Message 12 of 21
(2,340 Views)

Apparently there is a difference in LVRT, as I just created a project based on your example (I compiled the dll in LabWindows/CVI and called it StructureArrayRT.dll, and changed your VI to look for the DLL with this name, and I stuck the VI into a new Realtime project to run it on the target).  Anyway, when I run it, the realtime target either gives me a turquoise screen with a bunch of errors or the realtime target simply resets.

 

Heellllppp!!  Smiley Frustrated

0 Kudos
Message 13 of 21
(2,335 Views)

Could be a bug in LabVIEW RT. If that is the case then you need to file a support request at NI. However the only short term solution would be to pass the data in LabVIEW native format and do the translation in your wrapper. Not really that a big task actually, as all you need to do is changing the configuration of the CLN, as well as the declaration of the function and then passing the right values to your internal DLL.

 

Basically:

 

int32_t Load_Transmit_FIFO_RTx(uint32_t handle, uint16_t channel, 
	int32_t FIFOnumber, void data[], int32_t numWords, int32_t *actualLoaded, 
	int32_t *actualStartIndex)
{

	/* Insert code here */

 

 

would get:

 

typedef struct {
	int32_t control;
	int32_t data;
	} TD2;

typedef struct {
	int32_t dimSize;
	TD2 data[1];
	} TD1;
typedef TD1 **TD1Hdl;

#include "lv_epilog.h"

int32_t Load_Transmit_FIFO_RTx(uint32_t handle, uint16_t channel, 
	int32_t FIFOnumber, TD1Hdl *data, int32_t *actualLoaded, 
	int32_t *actualStartIndex);

{
      if (!*data)
return mgArgErr; // Empty array passed in

int32_t numWords = (**data)->dimSize;
void data[] = (**data)->data;
/* Insert code here */ }

 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 14 of 21
(2,322 Views)

Yes, since I have a wrapper I can do that. Clearly there is a problem because not always does one have the option of changing the DLL code.

 

The problem that I have is that the wrapper DLL is the same for both our LVRT and our regular LabVIEW products.  The only thing I can think of is to pass a void pointer, somehow know inside the DLL whether I was called from LVRT or LabVIEW, and then cast accordingly.  Ugly, but it should work.  But is there some simple way to know that I was called from LVRT?

 

Thank you.

 

Batya

0 Kudos
Message 15 of 21
(2,301 Views)

 Curiouser and curiouser...

 

Now I took your (Rolfk)'s example VI as it is, but compiled the DLL in LabWindows/CVI instead of Visual Studio and pointed the VI to that DLL (I called it StructureArrayRT.dll).

 

I ran it in LabVIEW without LVRT.  It crashed.

 

How could the compiler with which I compile the DLL affect how LabVIEW passes the array to it?!?

 

 

Thank you.

Batya

0 Kudos
Message 16 of 21
(2,294 Views)

@BPerlman wrote:

Yes, since I have a wrapper I can do that. Clearly there is a problem because not always does one have the option of changing the DLL code.

 

The problem that I have is that the wrapper DLL is the same for both our LVRT and our regular LabVIEW products.  The only thing I can think of is to pass a void pointer, somehow know inside the DLL whether I was called from LVRT or LabVIEW, and then cast accordingly.  Ugly, but it should work.  But is there some simple way to know that I was called from LVRT?

 

Thank you.

 

Batya


You can use the same code on both platforms. Just pass the LabVIEW native Data handle to your wrapper DLL and do the translation as I explained in there to pass the actual array data pointer to your internal dll, and do this on LabVIEW desktop and LabVIEW RT. Since the Call Library Node seems to pass the native data type correctly on both platforms that should work. According to your claims it's only the array data pointer that does not work as expected on LabVIEW RT. So by avoiding it and doing the case which works on RT also in your desktop version, you should be clear.

 

Basically that little code change I showed you for your wrapper DLL is all the Call Library node really does itself when you configure the array as passed as array data pointer. No real magic, just some convinience.

 

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 17 of 21
(2,289 Views)

@BPerlman wrote:

 Curiouser and curiouser...

 

Now I took your (Rolfk)'s example VI as it is, but compiled the DLL in LabWindows/CVI instead of Visual Studio and pointed the VI to that DLL (I called it StructureArrayRT.dll).

 

I ran it in LabVIEW without LVRT.  It crashed.

 

How could the compiler with which I compile the DLL affect how LabVIEW passes the array to it?!?

 

 

Thank you.

Batya


Are you sure your CVI compiler is not set to use stdcall calling convention by default? This setting can be set per function export through __cdecl or __stdcall declarations but can usually also be set globally as compiler option. Visual C uses __cdecl as default and I therefore didn't explicitedly add __cdecl to the function exports.

 

Would usually do that, but this was a quick and dirty test example.

Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 18 of 21
(2,288 Views)

Duh!  I should have remembered that.  Yes, the problem was the calling convention.

 

Now all the little examples I made based on yours, work.

 

So why doesn't my original VI?

 

Hmmmm.......still a mystery.

 

Batya

0 Kudos
Message 19 of 21
(2,275 Views)

Im sorry to hear you are still having issues getting your original VI to work. 

 

Have you tried integrating your dll code into the example one function at a time?

 

You can also try rebuilding your VI based on rolfk's example.

 

 

Trevor B.
PSE
National Instruments
0 Kudos
Message 20 of 21
(2,206 Views)