我需要將本機C++庫集成到C#項目中。現在在這個C++庫中,有一些類需要在C++/CLI中繼承的虛函數。 所以在C++/CLI我寫成才喜歡從C++庫調用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++調用委託。我還嘗試用[UnmanagedFunctionPointer(Cdecl)]定義CallbackDelegate的調用約定。我嘗試了所有選項,但沒有結果:我總是以異常結束,或者應用程序永遠掛起。有人能給我一些什麼可能是錯誤的暗示嗎?
Henrik的回答是好多了,委託對象並不需要是固定。此外,你可能*真的*不想使用Invoke()方法,它啓動一個新的線程。 –
我試過Bojan的建議,它的工作。 Invoke在C++/CLI中調用C#委託。我可以採取另一種方法來做到這一點嗎? – kvd
@nobugz'Invoke'不會啓動一個新的線程。在委託上調用'Invoke'與執行'del()'完全相同。 –