Мне нужно интегрировать нативную библиотеку C ++ в проект C #. Теперь в этой библиотеке C ++ есть класс с виртуальными функциями, которые мне нужно наследовать в C ++ / CLI.
Так что в C ++ / CLI я написал что-то вроде
class C++CliClass : public C++Class
{
C++CliClass(Callback callback) { iCallback = callback; }
virtual VirualFunctionCallFromC++(int x, int y, int z, SomeClass *p)
{
// I need to call C++/CLI here
iCallback(x, y, z, p);
}
private:
Callback iCallback;
}
I defined the callback function as:
typedef int (__cdecl *Callback)(int x, int y, int z, SomeClass *p);
The idea is now that C++ library calls the virtual function of the C++Cli
class which on his turn calls the call back which gets me hopefully into C#.
// This delegate definition is needed to setup the callback for the C++ class
delegate int CallbackDelegate(int x, int y, int z, SomeClass *p);
So now I defined a managed C++/CLI class
public ref class GCClass
{
public:
delegate <Byte>^ GetDataDelegate();
GCClass(GetData^ getDataDelegate) { iGetDataDelegate = getDataDelegate };
private:
GetDataDelegate ^iGetDataDelegate;
int GetData(int x, int y, int z, SomeClass *p)
{
// call delegate into C#
<Byte>^ data = iGetDataDelegate->Invoke();
}
public:
void SomeFunctionWhichEventuallyCallsC++Libary
{
// create a delegate for the method that will call the C# delegate
CallbackDelegate ^d = gcnew CallbackDelegate(this, &GCClass::GetData);
IntPtr del = System::Runtime::InteropServices::Marshal::GetFunctionPointerForDelegate(d);
// Install in the C++ class
C++CliClass(del.ToPointer());
// Setup the C++ library and install my C++ class into the library
SomeObjectOfTheLibrary->Install(&C++CliClass);
SomeObjectOfTheLibrary->DoSometing() // will call the C++ virtual function and end up in C#
// The delegate is no longer needed anymore
}
Пока здесь код. Так что я надеялся достичь того, что кто-то может вызвать метод моего управляемого класса C ++ / CLI, который использует собственную библиотеку C ++ для своей работы. В свою очередь библиотека C ++ вызывает обратный вызов C ++ / CLI и, наконец, вызывается делегат C #. Теперь, наконец, вопрос: все отлично работает в режиме отладки. Однако в режиме выпуска иногда генерируется AccesException, а иногда просто зависает приложение. Я подозреваю, что это как-то связано с различными соглашениями о вызовах для C ++ / CLI и C ++. Например, я заметил, что во время второго вызова обратного вызова значение iCallback отличается от первого вызова. Однако для всех последующих вызовов значение iCallback больше не меняется. Я ожидаю, что значение iCallback всегда должно быть одинаковым, но я не уверен, потому что я не знаю, как внутренне работает фреймворк, чтобы иметь возможность вызывать делегата из C ++. Я также попытался определить соглашение о вызовах CallbackDelegate с помощью [UnmanagedFunctionPointer (Cdecl)]. Я перепробовал все варианты, но безрезультатно: я всегда получаю исключение или приложение зависает навсегда. Может кто-нибудь подсказать, что может быть не так?