LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

vi reference = function pointer for external DLL?

Solved!
Go to solution

So I'm porting this simple program from C to LabVIEW. All it does is getting some signals from an haptics hardware (Sensable Phantom Omni). It should be simple, but it has shown several complications. (been stuck for 2 weeks Smiley Mad)

 

I successfully imported the hardware's DLL with all of its functions (using LV 8.2, because 8.5 and 8.6 's wizard sucks).

 

But there is a function whose argument is a function pointer:

 

hUpdateHandle = hdScheduleAsynchronous(updateDeviceCallback, 0, HD_MAX_SCHEDULER_PRIORITY);

 

I already have the corresponding VI for updateDeviceCallback (which gets a (void *) that does not really use, and returns an int).

hdScheduleAsynchronous is part of the hardware's API (I can't mess with it, nor I know what's inside), and as first argument expects a function pointer.

 

Can I use the Open VI reference node to get the 'pointer' for my VI and then feed it as an argument for the external DLL? How do I properly cast the VI ref datatype into a function pointer?

Download All
Message 1 of 6
(7,572 Views)

JavierRuiz wrote:

So I'm porting this simple program from C to LabVIEW. All it does is getting some signals from an haptics hardware (Sensable Phantom Omni). It should be simple, but it has shown several complications. (been stuck for 2 weeks Smiley Mad)

 

I successfully imported the hardware's DLL with all of its functions (using LV 8.2, because 8.5 and 8.6 's wizard sucks).

 

But there is a function whose argument is a function pointer:

 

hUpdateHandle = hdScheduleAsynchronous(updateDeviceCallback, 0, HD_MAX_SCHEDULER_PRIORITY);

 

I already have the corresponding VI for updateDeviceCallback (which gets a (void *) that does not really use, and returns an int).

hdScheduleAsynchronous is part of the hardware's API (I can't mess with it, nor I know what's inside), and as first argument expects a function pointer.

 

Can I use the Open VI reference node to get the 'pointer' for my VI and then feed it as an argument for the external DLL? How do I properly cast the VI ref datatype into a function pointer?


LabVIEW has no concept that can translate seemlessly to function pointers and there is certainly no sensible way to make the Call Library Node support something like this.

 

There are possibilities to create a DLL from your callback VI and import the function using Windows API calls to pass it as a function pointer to your other function. But this is involved and quite dirty and most importantenly a total nightmare to maintain, since things go completely awry if your DLL is created in a different LabVIEW version than the LabVIEW version you call it with. This may seem like a piece of cake now but whoever will have to upgrade your software to a new LabVIEW version later will love you to the point that they will feel like sending you as the original programmer a nice little present that blows in your face when opened Smiley Sad

 

The only feasable way is to write a wrapper DLL in C that translates between something more LabVIEW friendly like a user event and the actual callback function mechanisme.

 

Rolf Kalbermatter

Message Edited by rolfk on 06-09-2009 10:24 AM
Rolf Kalbermatter
My Blog
Message 2 of 6
(7,530 Views)

Thanks! 

 

Somewhere else I read that a good solution would be to get the function pointer with LoadLibrary and GetProcAddress in a C program, which I think is what you say will get me the present...

 

I'm quite newbie on callbacks and user events both in C and in LV, so I decided to give the above functions a try. (I even found that Wiebe already did the subVIs).

 

I wrote my subVI in C (actually, the original code I was using is in C), and built it into "QueryDevice.DLL". Then I wrote another mini program that uses LoadLibrary and GetProcAddress to that function and returns the FARPROC (function pointer, as I understand) and again built it into a second DLL (which I called WrapperDLL.DLL, though I know that's not the correct concept of Wrapper). It actually gets an int to choose between one of two functions I'll need.

 

So in LabVIEW I'm calling this WrapperDLL.DLL to get my function pointer, to try and feed it to the scheduling function. (and hope the things that come after that work).

 

Now the problem I have is that when the Call Library Node runs WrapperDLL.DLL, and this DLL loads QueryDevice.DLL, this latter uses a function hdInitDevice(). This is defined in hd.dll which is one of the main dlls to communicate with the hardare. The problem is that QueryDevice.dll is actually searching for the function hdInitDevice@4, a decorated name, and the function the DLL exports (as shown with dumpbin) is _hdInitDevice@4, with underscore. So I guess my problem now is on the C side. Some calling convention issue?

 

I guess my problem is pretty similar to his:

http://www.experts-exchange.com/Programming/Languages/CPP/Q_20627276.html

but I still don't exactly get what he did. Replace all function calls for LoadLibrary and GetProcAddress? Because my QueryDeviceDLL uses a lot of functions from this hd.dll, so I´m pretty sure that I'll be getting this error message for every one.

 

decorated.PNG 

 dumpbin.PNG

0 Kudos
Message 3 of 6
(7,473 Views)
Solution
Accepted by topic author JavierRuiz

Well that DLL probably uses the standard C calling convention and then Visual C likes to prepend an underscore before the exported name. LabVIEW's Call Library node works around that because when it tries to GetProcAdress a function name you have entered and that fails it does automatically retry with the function name with an underscore prepended. For your own "Wrapper DLL" you will have to either do something similar or use the right name.

 

But while the callback DLL does indeed need to be written in C to avoid troubles, the Load Library and GetProcAddress functions can be easily implemented directly in LabVIEW using the Call Library Node. It allows you to more easily fiddle with such things as function names.

 

Rolf Kalbermatter

Rolf Kalbermatter
My Blog
Message 4 of 6
(7,461 Views)

yeah! 😄

with some help from here and your suggestions and Wiebe's subVIs, I am now getting the function pointer for my C-writtten functions. A big nice number, which so far has stayed constant for each of my two functions. 

 

Now it is the Call Library node which is giving me troubles with the hdScheduleAsynchronous function (ERR1097), but I suspect it is something simple related to the function prototype (damn complex data types).

 

Thanks! 

0 Kudos
Message 5 of 6
(7,434 Views)

Hello 🙂  

Im trying to read and write motion and force data from & to Phantom Omni as one of my projects. I am quite new at this & want to run the labVIEW vi you have posted. Where can I get the following VIs? Your help on this will be very much appreciated 

-Get Current Device

-begin Frame

-Get integerv

-Get doublev

-Get Error

 

 

 

0 Kudos
Message 6 of 6
(5,718 Views)