C3374: невозможно получить адрес функции, если не создан экземпляр делегата
У меня возникли проблемы с использованием функции регистрации сторонней библиотеки для регистрации обратного вызова. Я пишу в C++ CLI и обращаюсь к библиотеке, написанной на C или C++.
Что означает вышеуказанная ошибка компилятора?
это функция регистрации, как определено продавцом:
MYCO int WINAPI MyCo_Device_Register_CallbackFunc(LPVOID func, LPVOID lpParam, DWORD mask);
это обратный вызов, как определено поставщиком:
typedef void (CALLBACK* MyCo_Device_CallbackProc)(DWORD ddStatus, LPVOID lpParam);
Моя функция обратного вызова:
public ref class Device
{
void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}
Мой звонок (который терпит неудачу):
MyCo_Device_Register_CallbackFunc((LPVOID) Device::CallBackFunc, nullptr, 0xFFFF);
2 ответа
Если бы мне пришлось отыграть предположение, вы пытаетесь взять адрес функции MANAGED и передать ее как указатель на функцию NATIVE. Это не сработает вообще. Либо напишите собственный мост (сложнее и, вероятно, без преимущества), либо (и это более простой подход) создайте делегата и используйте Marshal.GetFunctionPointerForDelegate. Не забывайте, что делегат должен оставаться в живых до тех пор, пока нативный код ожидает перезвонить, поэтому вам, скорее всего, нужно его где-то хранить.
Да, и все функции внутри класса ref или класса значений являются управляемыми функциями, в случае, если это неясно.
[РЕДАКТИРОВАТЬ] Расширение ответа, чтобы покрыть вопросы в комментариях. Первым шагом является создание соответствующего делегата. Для предоставленной вами функции она будет выглядеть так:
public delegate void CallbackFuncDelegate(DWORD ddStatus, LPVOID lpParam);
Затем вам нужно создать один:
CallbackFuncDelegate del = gcnew CallbackFuncDelegate(CallbackFunc);
И, как отмечалось ранее, вы должны хранить этот IN в своем классе в качестве члена, чтобы убедиться, что он не исчезает. Наконец, вам нужно получить указатель на функцию и передать его:
MyCo_Device_Register_CallbackFunc((MyCo_Device_CallbackProc) Marshal::GetFunctionPointerForDelegate(del).ToPointer(), 0, 0);
Я думаю, что это охватывает все. Все, что вам нужно, это использовать систему имен пространства; и ты должен быть в порядке.
Ваша функция обратного вызова - член - указатель на член и указатель на функции - это разные вещи.
Даже в решении Promit:
CallbackFuncDelegate(CallbackFunc)
CallbackFunc не должен быть членом класса
Вы можете написать просто
public ref class Device
{
static void CallBackFunc(DWORD ddStatus, LPVOID lpParam) {};
}
а затем использовать
Device::CallBackFunc