LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Passing a string buffer pointer to a DLL in LabVIEW

Hello Greg

Not sure what happened in my last posting but the LabVIEW error detail got missed off the posting!

In answer to your questions regarding the blank string buffer - I've tried 24 bytes, 48 bytes and 100 bytes of reserved space for the output string buffer from the DLL but LabVIEW always crashes with the usual "LabVIEW: An exception occurred within the external code called by a Call Library Node...", "VI was stopped at Call Library Node Function Node 0x6CC of subVI". The output of the DLL should return (I'm assuming) the data to the string indicator (check the Visual Basic, LabWindows/CVI and VC++ screen snapshots from previous postings) but all I receive is the LV error and no data returned from the DLL.

This DL
L is supplied by the hardware manufacturer and I cannot re-build or breakpoint the DLL as I do not have the source. I've also looked at the excellent "Call DLL.vi" example that ship with LV7.0 and have tried to replicate the Call Lib Node configuration in the VIs (WinCHAR.vi, ANSIunsignedchar.vi and LVCStr.vi).

Why is it that Visual Basic, LabWindows/CVI and VC++ can all execute this simple DLL call but LabVIEW seems to have a real problem?

-Chroma
0 Kudos
Message 11 of 15
(1,719 Views)
> This DLL is supplied by the hardware manufacturer and I cannot
> re-build or breakpoint the DLL as I do not have the source. I've also
> looked at the excellent "Call DLL.vi" example that ship with LV7.0 and
> have tried to replicate the Call Lib Node configuration in the VIs
> (WinCHAR.vi, ANSIunsignedchar.vi and LVCStr.vi).
>
> Why is it that Visual Basic, LabWindows/CVI and VC++ can all execute
> this simple DLL call but LabVIEW seems to have a real problem?
>

To initialize a buffer, you can use a string constant, a Format into
String, etc. If you split the wire and look at the data in an indicator
before the call, you can turn on \ codes and look at the size and
contents of the string going into the DLL.

I went to the devzone sight, and looked at the previous posts. Though
there is a lot of information there, not much is about what the DLL
expects the various inputs to be. The magic numbers you are printing
are addresses on the stack. Typeing those into P4 is not a good idea
since that address is either going to be outside the LV app resulting in
an instant exception being thrown by the OS, or it will be in the LV
process and will simply corrupt something.

So, wire up a string with verified contents and set the type to pascal
string. If the DLL tries to realloc or free the pointer, or if it
accesses data outside the input string buffer, it will throw an
exception. LV will catch the exception, and the outputs will not be
filled in.

If you are still unsuccessful, you can try out passing information into
your own DLL with the same signature. This gives you the ability to
look at exactly what LV is passing in. You can also give the info to
tech support and see if they can reproduce your problem.

As for why it is easy in one environment and not in another, I think
that will be more obvious when the mistake being made is figured out. I
assure you that many many DLLs are called by LV including many of the NI
I/O drivers. That isn't to say that there might not be a bug, but
people use this successfully all the time.

Greg McKaskle
0 Kudos
Message 12 of 15
(1,719 Views)
Hi Chroma,

I am linking Lab VIEW with a third party software using call dll function.
I am stuck up in the same position that u were in when u posted this question in the discussion forum.

Thisis the function I am trying to define to the dll call function,

/* ROUTINE LCOM_MasterGetLine

LCOM_RES LCOM_MasterGetLine(int ID,char*Buffer,int Length)

* Reads line of maximally Length characters from Slave ID into Buffer
* ARGUMENT(S) ID ... Slaves ID
* Buffer ... Where do you want chars (at least Length+1 in size)
* Length ... How many at most (should be less than LCOM_MAXLEN)

What I need to do is give the address of the buffer as an input to the call function, and in that address the labview stores the line that is given by
the third party software.

Then I should be able to read what is stored in that buffer,

I am attaching the VI here and the problem is in the fourth part of the VI,

I would be very helpful if u could help me with this.

Thanks
Ajit
0 Kudos
Message 13 of 15
(2,283 Views)
Pascal calling convention is obsolete in Win32. It has nothing to do with Pascal string parameters but rather is similar to the cdecl and stdcall calling conventions you can configure in the Call Library Node.

Rolf K
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
0 Kudos
Message 14 of 15
(1,719 Views)
What your problem with this is is the following assuming you declared it as this:

static unsigned char MemoBuffer[MEMO_BUFFER_SIZE];

p4 = (int)&MemoBuffer;

hasp(MEMOHASP_READBLOCK, SeedCode, PortNum, Pass1, Pass2, &p1, &p2, &p3, &p4)

First you assign to p4 a reference (pointer) to the pointer of the memobuffer, and then you pass a reference to the reference to the memobuffer to the function.

Unfortunatly there is no simple way you can do this directly in LabVIEW. It is similar to a LabVIEW handle wich is also a pointer to a pointer but LabVIEW will bark on returning of the Call Library Node as the first four bytes will be filled in by some returned data but LabVIEW expects an int32 in there telling it how many array elements do follow.

The most si
mple solution is to just create a small wrapper C function in a DLL or CIN to deal with this. Basically calling the Visual Basic memory preparation routine would probably take care of that.
Another possibility might be to try to create such a reference to a pointer with some LabVIEW magic. You could use a Call Library Node with:

library: LabVIEW
function: MoveBlock
calling convention cdecl
return: void
param1: s (your uInt8 array as C array)
param2: t (a uInt32 passed by reference)
param3: len (an uInt32 passed by value with value 4)

Take the output of the t variable which is the pointer to your buffer now. If the declaration of your buffer was as I did assume you would have to repeat this trick once more I would guess, and the returning uInt32 can then be passed as an uInt32 passed by reference to the function.

Tricky, trial and error and a little hard to explain like this.

Rolf K
Rolf Kalbermatter  My Blog
DEMO, Electronic and Mechanical Support department, room 36.LB00.390
Message 15 of 15
(1,719 Views)