Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C3374: can't take address of 'function' unless creating delegate instance

Tags:

.net

clr

c++-cli

I am having difficulty using a thirdparty library registration function to register a callback. I am writing in C++ CLI, and accessing a library written in C or C++.

What does the above compiler error mean?

this is the registration function as defined by the vendor:

MYCO int WINAPI MyCo_Device_Register_CallbackFunc(LPVOID func, LPVOID lpParam, DWORD mask);

this is the callback as defined by the vendor:

typedef void (CALLBACK* MyCo_Device_CallbackProc)(DWORD ddStatus, LPVOID lpParam);

My callback function:

public ref class Device 
{
    void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}

My call (which fails):

MyCo_Device_Register_CallbackFunc((LPVOID) Device::CallBackFunc, nullptr, 0xFFFF);
like image 721
MedicineMan Avatar asked Jan 24 '23 15:01

MedicineMan


1 Answers

If I had to wager a guess, you're trying to taken the address of a MANAGED function and pass it as a NATIVE function pointer. That won't work at all. Either write a native bridge (harder and probably no advantage), or (and this is the easier approach), create a delegate and use Marshal.GetFunctionPointerForDelegate. Don't forget that the delegate has to stay alive for the duration that the native code expects to call back, so you most likely need to store it somewhere.

Oh, and all functions inside a ref class or value class are managed functions, in case that wasn't clear.

[EDIT] Expanding answer to cover questions in comments. The first step is to create a matching delegate. For the function you provided, it's going to look like this:

public delegate void CallbackFuncDelegate(DWORD ddStatus, LPVOID lpParam);

Then, you'll need to create one:

CallbackFuncDelegate del = gcnew CallbackFuncDelegate(CallbackFunc);

And as noted previously, you should store that IN your class as a member in order to make sure it doesn't vanish. Lastly, you need to get the function pointer and pass it down:

MyCo_Device_Register_CallbackFunc((MyCo_Device_CallbackProc) Marshal::GetFunctionPointerForDelegate(del).ToPointer(), 0, 0);

I think that covers everything. All you need is using namespace System; and you should be fine.

like image 178
Promit Avatar answered Jan 30 '23 13:01

Promit