C3374: не может получить адрес функции, если не создан экземпляр делегата

StackOverflow https://stackoverflow.com/questions/822582

  •  03-07-2019
  •  | 
  •  

Вопрос

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

Решение

Если бы мне пришлось отыграть предположение, вы пытаетесь взять адрес функции 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
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top