Я пытаюсь создать оболочку для 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*, но ничего не помогло мне заставить это работать
Спасибо.