Насколько я знаю, это невозможно сделать таким образом.Методы не «там», как у полей, кроме того, создание структуры с помощью виртуального метода создаст указатель vtable в ваших объектах, который вы не учитываете в c # зеркальном классе.
То, что вы можете сделать, - это вызвать PInvoke для метода, который принимает functionPointer (в C ++) и передает туда делегат (C #).Затем вы можете использовать этот указатель на функцию для вызова его из собственного кода, и ваш делегат запустится.
Затем вы можете изменить определение метода stateChange, чтобы принимать Callback * в качестве первого параметра, поэтому при вызове его из nativeВ коде вы можете передать указатель на объект, который отвечает за это изменение, и направить его обратно в Callback в c #.
// Редактировать, не имея исходного кода dll, построить мост между c # и c ++ - это то, что приходит к моемуразум.Это можно сделать с помощью c ++ / cli или c ++, придерживаясь нативной моей идеи, что-то вроде этого:
//c++ <--> new c++ dll <--> c#
struct CallbackBridge : public Callback
{
void (*_stateChanged)(int);
virtual void stateChanged(int state)
{
if (_stateChanged)
_stateChanged(this, state);
}
};
void* CreateCallback() { return new CallbackBridge(); }
void DeleteCallback(void* callback); { delete callback; }
void setStateChanged(void* callback, void (*ptr)(void*, int))
{
CallbackBridge* bridge = (CallbackBridge*)callback;
bridge->stateChanged = ptr;
}
///... other helper methods
Идея здесь состоит в том, чтобы рассматривать ваш объект как черный ящик (следовательно, void * везде - этоможет быть любым указателем, но из c # вы просто увидите это как SafeHandle / IntPtr и напишите вспомогательные методы, которые вы можете использовать для создания / удаления и изменения объектов PInvoke.
Использование c # может выглядеть следующим образом: (IntPtr для простоты можно использовать SafeHandle):
IntPtr callback = CreateCallback();
SetStateChanged(callback, myCallback);
//somewhere later:
DeleteCallback(callback);
void MyCallback(IntrPtr callback, int state)
{
int someData = SomeOtherHelperMethod(callback);
ConsoleWrite("SomeData of callback is {0} and it has changed it's state to {1}", someData, state);
}
Я знаю, это немного неуклюже для больших объектов, но без c ++ / cliОбертка Я никогда не находил лучшего способа справиться со всеми такими сложными делами, как виртуальные вызовы и т. д.