LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

DLL calling convention

Hello
Here's my problem. DLL looked always magic to me, so I tried to work with them to see how it works. I wrote a DLL in Labwindow/CVI 6.0 and my first fonction had the following prototype

extern int __cdecl MyDLL_Init (int In1,char *Out2);

I did'nt exactly know why using a C type declaration or a standard one but the I followed a typical example found in the Developer zone. Actually my function had one integer input (In1) and two output: a status Integer and a C string parameter. I called the function in Labview 6i following the example given and I was surprised that everything worked the first time. I wanted to add another output string to my function, so I changed the prototype

extern int __cdecl MyDLL_Init (int In1,char *Out
2,char *Out3);

I changed the configuration in Labview Call Library Function and then Labview crashed all the time. I tried to call the DLL in a CVI program and everything went well. I came back to Labview and it crashed again. I came back to the first prototype and it worked well. I thought it might be the fact that Labview does not use C type string but it worked fine with only one output string, so it does do the conversion if the String Format is correctly chosen in the configuration. Finally I just changed the convention from cdecl to stdcall and everything worked well. As a mechanical engineer, I am more a self-taught programmer and most of the time I change everything till it works without understanding very well but I wonder why this happens like this.
Thank you very much
Louis
0 Kudos
Message 1 of 2
(3,496 Views)
> Here's my problem. DLL looked always magic to me, so I tried to work
> with them to see how it works. I wrote a DLL in Labwindow/CVI 6.0 and
> my first fonction had the following prototype
>
> extern int __cdecl MyDLL_Init (int In1,char *Out2);
>
....


> extern int __cdecl MyDLL_Init (int In1,char *Out2,char *Out3);
>

I'm not certain if this was a story or a request for an explanation, but
I'll give you my thoughts as to what you were seeing.

Both of these declarations are similar in that they pass one int by
value, and one or two string buffers by pointer. The string pointers,
or anything else by reference/pointer are the ones to watch for. The
problem here is that C just isn't very informative as to what this
really is. This could be a pointer to a single char, to an array of
char on the stack, or to an allocated block of memory. It could also be
NULL.

From the rest of your description, you intended to use it as an output.
The key here is that you, the caller, have to give the callee a buffer
to write into. The buffer belongs to the caller, the callee cannot
resize it, alloate it, or delete it. The callee just writes into the
buffer and in some way lets the caller know how many elements are there.
On return, the caller can read the data, resize, reuse, or destroy its
buffer. With more calls back and forth, or a more intertwined
relationship between the DLL and EXE, you can have the buffer be owned
by the DLL or even a third party, but the normal is that the caller owns
it. What you were probably seeing is that the CVI caller had a char[]
with enough space for the result. In LV, this is equivalent to putting
a string constant or initializing a string of the same size. If you
pass an empty string, that is equivalent to using char[1] in CVI, and
that will crash too.

As for the convention, typically called the calling convention, __cdecl
is one of the most widespread on other platforms, and I'm not sure where
std_call or standard came from. Anyway, I think there are four main
conventions that use the stack, and numerous others that use registers.
They main differences are who cleans up the stack (caller or callee),
and which order are the parameters on the stack. Some platforms have
one convention, others have another, and presumeably the common standard
is the one that is most resilient to bad calls or is the highest
permance one. Regardless, it is something that you have to get right.
About the only way to do that is read the header file or documentation
for the DLL. And on widows, they "wisely" chose to have most user
libraries use one standard and the OS libraries use the other, so you
have to pay attention to it. Actually, between the beta of NT 3.5 and
the release, they changed the convention and surprised everyone. We may
never know why.

Greg McKaskle
Message 2 of 2
(3,496 Views)