LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

DLL Function Call questions

 

Hello,

 

I have some questions about calling a function in LabVIEW from a DLL file.

 

The function I am interested is basically like this:

SendFileA(HANDLE handle, const char *src_filename, CustomProc progress);

 

the "progress" variable is a structure, which is like this if I understand it correctly:

 

CustomProc(unsigned long size, unsigned long pos);

 

I can use this function to track the file progress. But I am not quite sure how to use it in LabVIEW. I can use it in C easily enough.

 

How do I configure a DLL call in LabVIEW, and use the structure variables to track my progress?

 

Similarly, I can pass a NULL in palce of the progress. Do I pass a NULL as a string input? How can I pass a null?

 

I am passing progress into the DLL as an Adapt to Type, Handles by Value.

The Call Library Function is coming up with a prototype like this:

uint32_SendFileA(uint32_t Handle, CStr src_filename, void *progress);

 

I am sorry in advance, but that's all I can share.

Veni Vidi Duci
0 Kudos
Message 1 of 13
(5,560 Views)

DB_IQ wrote: 

the "progress" variable is a structure, which is like this if I understand it correctly:

 

CustomProc(unsigned long size, unsigned long pos);

 

I can use this function to track the file progress. But I am not quite sure how to use it in LabVIEW. I can use it in C easily enough.


Can you provide some example code showing how you use it in C? From the way you've described it and from the name, CustomProc sounds like a pointer to a callback function, not a structure. If that's the case, you'll need to create an additional DLL that implements the callback and provides some communication with LabVIEW (through user events or other means). There are examples of this on the forum, but they require some understanding of C. You cannot do this purely in LabVIEW.


@DB_IQ wrote:

Similarly, I can pass a NULL in palce of the progress. Do I pass a NULL as a string input? How can I pass a null?


Wire in a constant 0, with that parameter configured as a pointer-sized integer passed by value.

0 Kudos
Message 2 of 13
(5,555 Views)

nathand is correct, CustomProc is a callback function pointer and that is one thing LabVIEW can't really do. Even if it could, you would not want to deal with the necessary configuration dialog, where configuring the Call Library Node itself is absolute peanuts in comparison. Function pointers is something that even very seasoned C programmers often struggle with.

 

And as nathand pointed out, you would need to implement a wrapper DLL in C(++) (or if you are more comfortable with for instance Delphi) that implements this callback function and translates it into something else that is LabVIEW compatible such as a user event.

 

But unless you really need that feature, I recommend you to simply avoid it by passing a NULL value to it, as your documentation seems to indicate you can do. And nathand is correct about that for this you need to configure the parameter as pointer sized integer, passed by value, and wire a 0 constant to it.

Rolf Kalbermatter
My Blog
0 Kudos
Message 3 of 13
(5,504 Views)

I was looking at this note:

http://digital.ni.com/public.nsf/allkb/89165EDE5031C68686257B2E0006FE99

which describes the same wrapper method previously mentioned, but frustratingly there are no examples available as mentioned in the article.

But I found a similar link here:

http://zone.ni.com/reference/en-XX/help/371361K-01/lvhowto/creating_user_events/

 

I understand the user events and all that. I just got to figure out the C Wrapper DLL next.

 

I am going to look at the DLL wrapper, as time permits. Once I have something working, I will mark it as a solution.

Thanks for the suggestions 🙂

Veni Vidi Duci
0 Kudos
Message 4 of 13
(5,430 Views)

So, may I ask the best method for making a wrapper for this CustomProc progress variable mentioned above?

 

The format in the DLL I am using is like this:

typedef CUST_ERR (WINAPI *CustomProc)(unsigned long x, unsigned long y);

 

What I would like is to be able to call the wrapper from my Labview program and get the value of x and y.

 

See, I am not sure I CAN write a wrapper on this, becasue it's not a function that LabVIEW even recognizes as a function.

Especially since it's a type def.

Veni Vidi Duci
0 Kudos
Message 5 of 13
(5,331 Views)

The best way is writing a wrapper DLL in C which implements this callback function. And to decide how you want to pass back the information from the callback function to LabVIEW. One possibility is to use a user event in LabVIEW.

 

First you implement a C function that you can pass the user event refnum from LabVIEW. This function then stores the user event refnum somewhere where the callback function can access it, and then calls the function to register your own callback function.

 

Then you implement the callback function itself in C. This function basically retrieves the user event refnum from where you stored it in the previous function, then calls the PostLVUserEvent() LabVIEW manager function with the event data.

 

You probably also want to create a function to unregister the callback too.

 

That's all that is really necessary. But it involves writing C code to create a wrapper DLL that you can call from LabVIEW, and this wrapper DLL then calls functions in your original DLL. 

Rolf Kalbermatter
My Blog
0 Kudos
Message 6 of 13
(5,321 Views)

Sure I get the understanding, I am having a hard time visualizing the code.

What I really could use is an example, if there is one.

 

PostLvUserEvent did not appear in my help file for CVI.

A quick search brought up this:

MgErr PostLVUserEvent(LVUserEventRef ref, void *data);

This function gets called inside the C Wrapper DLL.

My LabVIEW function will pass the reference to the user event on the DLL Call, if I follow you.

Veni Vidi Duci
0 Kudos
Message 7 of 13
(5,314 Views)

@DB_IQ wrote:

See, I am not sure I CAN write a wrapper on this, becasue it's not a function that LabVIEW even recognizes as a function.

Especially since it's a type def.


It's not a function. It's a type definition. The type that it defines is a function with certain parameters. You need to create a function that fits that type definition. You then pass a pointer to that function - the address of the function - as the progress parameter to the SendFileA function, and while SendFileA is running it calls your function periodically.

0 Kudos
Message 8 of 13
(5,313 Views)

PostLVUserEvent() is not a CVI function. It's a function that is provided by the LabVIEW kernel. You will have to liink your DLL with labviewv.lib in the cintools directory inside your LabVIEW directory.

 

Have a read of this thread here: http://forums.ni.com/t5/LabVIEW/LabView-user-event-from-external-dll-source/m-p/726883. It will give you quite a bit of information and even some sample code too. But it will still be a lot of work and require quite a bit of understanding of C programming to make this work reliably for your particular situation. 

Rolf Kalbermatter
My Blog
0 Kudos
Message 9 of 13
(5,302 Views)

Thank you so much for the diligent assistnance thus far, I really appreciate it.

I did find the PostLVUserEvent just before you posted it.

 

I wrote the prototype for my wrapper, and it compiles fine. But I just want to make sure I got this correct.

 

Here is the function I have in my wrapper

 

int DLLEXPORT Function(LVUserEventRef *ref, int param)
{

    PostLVUserEvent(*ref, (void *)&param);
   

    return 0;
}

 

So, ref is the reference created by the LabVIEW Create User Event Function VI, according to the examples I saw.

But I am a little fuzzy on the param. Should param be the address location of the typedef function with the variables I want to access?

The second loop here is where my DLL wrapper call will go, but I haven't implemented it yet.

 

Should param be an int (for an address) or should it be the structure of two unsigned long's that I have inside the LabVIEW cluster?

 

Untitled.png

Veni Vidi Duci
0 Kudos
Message 10 of 13
(5,262 Views)