LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

Using DLL with complex Structures

I want to use the CALL LIBRARY FUNCTION to access a function in a DLL (MyDLL.dll) which returns a pointer to a structure in its parameter list (see below). How can I do it under LV7?
I am calling the C function "initialise" whose declaration is shown below:

----------------------------------------------------------------------------
long initialise(unsigned char *Num, Config **cfg, List *alarms);
----------------------------------------------------------------------------

Where the structures are defined as follows:

---------------------------------------
struct Config
{
unsigned char sensor_id;
unsigned short offset_time;
double sample_rate;
unsigned short buffer_len;
} ;
-------------------------------------
-------
struct List
{
CAlarm *alarms[255];
} ;
------------------------------------------------
struct CAlarm
{
TimeStamp time_stamp;
unsigned char src_channel
char area[255];
unsigned char priority;
char msg[255];
} ;
----------------------------------------------------
The DLL is compiled with MS Visual C++ v6.

Many thanks for your help.

Hanich.
0 Kudos
Message 1 of 4
(2,839 Views)
> ----------------------------------------------------------------------------
> long initialise(unsigned char *Num, Config **cfg, List *alarms);
> ----------------------------------------------------------------------------
>
> Where the structures are defined as follows:
>
> ---------------------------------------
> struct Config
> {
> unsigned char sensor_id;
> unsigned short offset_time;
> double sample_rate;
> unsigned short buffer_len;
> } ;
> --------------------------------------------
> struct List
> {
> CAlarm *alarms[255];
> } ;
> ------------------------------------------------
> struct CAlarm
> {
> TimeStamp time_stamp;
> unsigned char src_channel
> char area[255];
> unsigned char priority;
> char msg[255];
> } ;
> ----------------------------------------------------

I'm having to make some guesses here since I don't have the full
documentation or even the full API. It look like the DLL intends to
return a pointer to the Config struct, either you are supposed to call
back later to release it, or it is static storage that you just share
with the DLL.

LV data is pretty dynamic and LV wants to have allocated all of the data
that its generated code affects. This is in part due to the scheduling
that goes on to execute, and partly to simplify things. If you write a
wrapper DLL that takes that pointer and copies the fields into a LV
cluster passed into the wrapper by Adapt To Type, then LV will be happier.

The last parameter looks like something you are supposed to allocate
storage for and the DLL will fill in. It also causes some difficulty
since LV currently use handles for nested allocations and it looks like
the List is 255 pointers to a struct. A LV array of clusters will have
the CAlarm info inline and an array of arrays will look like 255
pointers to pointers to structs. If you have access to the C code, you
can look at introducing an initialise2 function with a more LV friendly
function signature, or you can build that in the wrapper DLL. For the
second one, I'd make an array of clusters. In the cluster put a
timestamp, whatever that is, followed by the u8, then a cluster of 255
u8s, then a u8, then a cluster of 255 u8s. Initialize the array to be
255 elements big and call the wrapper. In the wrapper, make a stack
based array of pointers to the LV clusters and send that to the original
DLL. The DLL will automatically write into the LV clusters so there is
nothing to do on the way back out of the DLL.

Also, determine if the storage of the Config needs to be freed later and
arrange for that to happen. You may need to return the pointer to LV as
an int32 and pass it in to a later DLL call for release.

Greg McKaskle
0 Kudos
Message 2 of 4
(2,839 Views)
Hi Greg,

Thank you so much for your help. I am new to LV,
so would you please give more details about your suggestion.

Regards,

Hanich.
0 Kudos
Message 3 of 4
(2,839 Views)
I'm not sure there is alot more I can give without being able to read the documentation for the functions being called. Personally, I'd start by dropping a Call By Reference node, configuring it to have three inputs and an I32 return value. The first input should be an unsigned U8 Pointer to Value. The second and third should be adapt to type Handles by Value.

Next wire it up on the diagram like in the attached picture. Then popup on the node and Create .c file. You now have your wrapper DLL started and in your C code you need to call the original DLL and then transfer info back into the structure LV gives you. As I mentioned, there are some tricks such as passing an array of pointers to the LV structures and letting the subD
LL just write straight into the LV clusters, but any way that you do it will be fine as long as you don't corrupt things.

If you have further questions, please be more specific.

Greg McKaskle
0 Kudos
Message 4 of 4
(2,839 Views)