Как вызвать функцию в C++ Dll из C#, которая имеет обратный вызов void*и объектный параметр

Я пытаюсь создать оболочку для C dll и пытаюсь вызвать функцию, которая принимает функцию обратного вызова, получает объект в качестве указателя, который передается обратно.

Файл.h задерживает

extern int SetErrorHandler(void (*handler) (int, const char*, void*),
                              void *data_ptr);

Обработчик — это функция обратного вызова, которая вызывается при возникновении ошибки, а data_ptr — это любой объект (state), который передается вам обратно в случае моего приложения, это будет просто (текущий объект).

Я могу вызывать функции в dll, которая использует упорядоченные константные типы, такие как простые типы, строки, целые числа и т. д. Но я не могу понять, как просто маршалировать указатель на объект C#, который является состоянием.

Чтобы передать ссылку на объект в функцию C из того, что я нашел, выполнив поиск здесь, и в противном случае кажется, что мне нужен тип структуры, чтобы иметь возможность сортировать функцию, поэтому я создал структуру для хранения моего объекта:

[StructLayout(LayoutKind.Sequential)]
struct MyObjectState
{
   public object state;
}

​​РЕДАКТИРОВАТЬ:Я попытался поместить атрибут:[MarshalAs(UnmanagedType.Struct, SizeConst = 4)]в свойство public object state, но это приводит к той же ошибке, поэтому я удалил его, похоже, он все равно не будет работать.

Структура содержит одно свойство объекта для хранения любого объекта для функции обратного вызова.

Я объявил делегат в C#следующим образом:

delegate void ErrorHandler(int errorCode, IntPtr name, IntPtr data);

Затем я объявил функцию импорта в C#следующим образом:

[DllImport("somedll.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int SetErrorHandler handler, IntPtr data);

Затем я создал функцию обратного вызова в своем коде C#:

void MyErrorHandler(int errorCode, IntPtr name, IntPtr data)
{
    var strName = Marshal.PtrToStringAnsi(name);
    var state = new MyObjectState();
    Marshal.PtrToStructure(data, state);
    Console.WriteLine(strName);
}

I я могу вызвать библиотечную функцию следующим образом:

var state = new MyObjectState()
{
    state = this
};
IntPtr pStruct = Marshal.AllocHGlobal(Marshal.SizeOf(state));
Marshal.StructureToPtr(state, pStruct, true);
int ret = SetErrorHandler(MyErrorHandler, pStruct);

Вызов работает, и функция обратного вызова вызывается, но я не могу получить доступ к данным в функции обратного вызова, и когда я пытаюсь Marshal.PtrToStructureя получаю сообщение об ошибке:

Структура должна не быть классом стоимости.

Я много искал здесь и нашел разные вещи о Marshall и void*, но ничего не помогло мне заставить это работать

Спасибо.

7
задан David Heffernan 12 April 2012 в 07:41
поделиться