所以我在C#中爲C DLL寫封裝。問題是一些功能使用複雜數據類型例如爲:C#dllimport跨平臺的複雜數據類型?
ComplexType* CreateComplexType(int a, int b);
有沒有一種方法,我可以宣佈一個有效的C#類,這樣我可以使用dllimport的? 如果我在做一個純Windows的解決方案,我可能會使用C++/CLI作爲本地複雜類型和託管複雜類型之間的中介。
我確實可以訪問C dll的源代碼,那麼是否可以使用不透明類型(例如句柄)?
所以我在C#中爲C DLL寫封裝。問題是一些功能使用複雜數據類型例如爲:C#dllimport跨平臺的複雜數據類型?
ComplexType* CreateComplexType(int a, int b);
有沒有一種方法,我可以宣佈一個有效的C#類,這樣我可以使用dllimport的? 如果我在做一個純Windows的解決方案,我可能會使用C++/CLI作爲本地複雜類型和託管複雜類型之間的中介。
我確實可以訪問C dll的源代碼,那麼是否可以使用不透明類型(例如句柄)?
對於在Windows和Linux中使用P/Invoke,單聲道有很好的documentation page。具體來說,請參閱封送處理部分,討論簡單類型和複雜類型。如果你想創造性,你可以將你的類型序列化爲一些方便的基於字符串的格式,如JSON或XML,並將其用作編組機制。
這樣的功能很難從C程序中可靠地調用,但在拼貼時它不會變得更好。問題在於內存管理,那個結構需要被再次銷燬。這要求調用程序使用與DLL相同的內存分配器。這在C程序中很少出現,但您可能很幸運擁有DLL的源代碼,因此您可以重新編譯它並確保每個人都使用相同的共享CRT版本。
當然,C#沒有這樣的運氣,pinvoke編組會調用CoTaskMemFree()來釋放結構。很少有真正的C程序使用CoTaskMemAlloc()來分配結構,因此這是XP的無聲故障,Vista和更高版本的AccessViolationException。現代Windows版本有一個更嚴格的堆管理器,不會忽略無效指針。
您可以聲明返回值爲IntPtr
,即停止拼接編組器試圖銷燬它。然後用Marshal.PtrToStructure()
手動編組。這不會阻止內存泄漏,您的程序最終會與OOM崩潰。無論如何。