C3374: не может получить адрес функции, если не создан экземпляр делегата - PullRequest
4 голосов
/ 05 мая 2009

У меня проблемы с использованием функции регистрации сторонней библиотеки для регистрации обратного вызова. Я пишу в 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 ]

9 голосов
/ 05 мая 2009

Если бы мне пришлось отыграть предположение, вы пытаетесь взять адрес функции 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);

Я думаю, что это охватывает все. Все, что вам нужно, это использовать систему имен пространства; и с тобой все будет в порядке.

0 голосов
/ 05 мая 2009

функция обратного вызова является членом - указатели на члены и указатели на функции - это разные вещи.

Даже в решении Promit:

CallbackFuncDelegate(CallbackFunc)

CallbackFunc не должен быть членом класса

Вы можете написать просто

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

и затем используйте

Device::CallBackFunc
...