LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

External Function with a Pointer to a Callback Function Inside a DLL

Solved!
Go to solution

Hi.

 

I'm loading a DLL and trying to call a function with the following prototype:

Func1(HANDLE, hHandle, LPVOID (*pCallback)(UINT, UINT LPVOID), CHAR* sPath)

 

Now, I have no problem with the variable types, because CVI 9.0.1 recognizes all of them and I have no problem with LoadLibrary() nor with GetProcAddress().

 

But, how do I pass a pointer to a callback that is inside the DLL I'm trying to use.

 

I've tried to declare the callback like this:

LPVOID (CALLBACK Callback)(UINT iDevNo, UINT evEvent, LPVOID pData);

and call the function Func1 like this:

(Func1)(hHandle, &Callback, NULL);

but this gets me:

 Undefined symbol '_Callback@12' referenced in "source.c".

Hope I can get some help.

I appreciate your time on this issue.

 

Regards.

Daniel Coelho
VISToolkit - http://www.vistoolkit.com - Your Real Virtual Instrument Solution
Controlar - Electronica Industrial e Sistemas, Lda
0 Kudos
Message 1 of 6
(5,409 Views)
Solution
Accepted by topic author Daniel Coelho

Hi Daniel,

 

First, you have to make sure that the callback function is exported by the DLL, so that the program that uses the DLL can access the function name identifier. Then, you have to make sure that you call GetProcAddress not just on Func1, but also on the exported callback function. You need to store both function address values in their respective function pointers. You then can pass the callback function pointer as an argument to the Func1 call.

 

It's probably cleaner if you define typedefs for all your function pointers, in the calling program:

 

typedef LPVOID (__stdcall *CallbackType) (UINT , UINT, LPVOID);
typedef ??? (__stdcall *Func1Type) (HANDLE, hHandle, CallbackType, CHAR*);

 

...


CallbackType     CallbackPtr;
Func1Type        Func1Ptr;

...


dllHandle = LoadLibrary ("...");
CallbackPtr = (CallbackType)GetProcAddress (dllHandle, "Callback");
Func1Ptr = (Func1Type)GetProcAddress (dllHandle, "Func1");

...


Func1Ptr (..., hHandle, CallbackPtr, NULL);

 

Boa Sorte!

Luis

Message 2 of 6
(5,374 Views)

Olá Luís.

 

Thank you for your reply.

Just to keep things clear, I'm trying to use a DLL that operates with an USB device.

 

I'm doing things as you say, using typedefs and all, but the DLL only exports 4 functions and none of them is the Callback function so I can't call it by its name identifier.

 

(NOTE:

I used TestStand to see what functions are visible in the DLL and I'm sure that the Callback function isn't exported.

And due to the specific types that these functions require, I'm not able to test the DLL on TestStand by itself.)

 

How else can I do this?

Daniel Coelho
VISToolkit - http://www.vistoolkit.com - Your Real Virtual Instrument Solution
Controlar - Electronica Industrial e Sistemas, Lda
0 Kudos
Message 3 of 6
(5,370 Views)

Well, that does sound like a problem then. If the callback function is intended to be private, inside the DLL, then it really can't be referenced outside of the DLL.

 

Do you happen to know what the intention was, on the part of the creators of the DLL, for what users should pass as the callback parameter of Func1? It would make more sense to me that the users would pass their own function, which presumably the DLL would later call. In other words, you'd be registering your own callback function with the DLL.

 

Why would you want to specify one of the DLL's hidden functions as the callback, rather than your own function?

 

Luis

0 Kudos
Message 4 of 6
(5,358 Views)

The documetation on this DLL is short...

 

I was sure that the Callback was inside the DLL but I was wrong.

In fact, the DLL calls my callback that I have to declare as:

LPVOID (CALLBACK Callback)(UINT iDevNo, UINT evEvent, LPVOID pData)
{
   //manage code
}

When I call USB_Init (I was calling it Func1 for explanation purpose only) like this:

(USB_Init)(hHandle, &Callback, sPath)

I receive a call to Callback function.

 

I think I misunderstood the documentation.

The DLL catches the USB device (dis)connection message and sends WM_DEVICECHANGE

to my application through hHandle and information about the device through the callback.

 

I'm sorry but I've never seen code work like this.

 

Now, Luis, can you please redirect me to a NI post where I can find a way to catch the WM_DEVICECHANGE through the hHandle?

 

I've tried:

InstallWinMsgCallback (panelHandle, WM_DEVICECHANGE, UsbCallback, VAL_MODE_IN_QUEUE, NULL, &postHandle);

But I think this is not the way the DLL intended me to catch the WM_DEVICECHANGE message.

 

Daniel Coelho
VISToolkit - http://www.vistoolkit.com - Your Real Virtual Instrument Solution
Controlar - Electronica Industrial e Sistemas, Lda
0 Kudos
Message 5 of 6
(5,338 Views)

No, I don't think you should use InstallWinMsgCallback for this purpose. That function is used when you want to receive low-level messages from Windows that are associated with a given panel's window. But in this case, it's the usb driver that needs to notify you. It sounds like the driver sends this message to your callback function whenever the device is disconnected.

 

Looking at the callback function's signature, my best guess is that it would pass WM_DEVICECHANGE as the evEvent parameter (it doesn't look like the hHandle is passed to the callback function). It might also pass some additional information about this event through the pData parameter, but without some documentation it would be hard to guess what this data might be.

 

Luis

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