2011-07-24 69 views
2

我正在C++/CLI中編寫一個包裝C DLL的包裝,以便它可以通過託管程序集在C#中訪問。使用直接P/Invoke通過C#訪問C函數是不可能的,因爲C DLL會引發使用P/Invoke無法正確捕獲的異常(在跨C/C#邊界移動時異常消息會丟失)。所以我們的想法是創建一個託管CLI DLL,它在內部調用C DLL並將異常封裝到CLI的Exception類中。C++/CLI雙指針類型轉換爲引用IntPtr的C#訪問

所以C DLL函數有這個聲明。

void InitDB(void **handle); 

的C#應用​​程序將需要進行以下聲明

void InitDB_cs(ref IntPtr handle); 

要做到這一點,我創建C++/CLI函數聲明如下

void InitDB_clr(IntPtr %handle); 

但是,我不能強制轉換REF InPtr成C功能。我嘗試使用下面的代碼,但似乎無法得到類型轉換的權利。對於上面的代碼

error C2440: 'initializing' : cannot convert from 'void *' to 'cli::pin_ptr<Type>' 
1>  with 
1>  [ 
1>   Type=System::IntPtr 
1>  ] 
1>  Conversion from 'void*' to pointer to non-'void' requires an explicit cast 
1>error C2664: 'InitDB' : cannot convert parameter 1 from 'cli::pin_ptr<Type> *' to 'void **' 
1>  with 
1>  [ 
1>   Type=System::IntPtr 
1>  ] 
1>  Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast 
+0

誰是Init()? –

+0

抱歉打字錯誤。它的InitDB(C DLL函數)。感謝您提醒我注意。 –

+0

沒有問題。我不知道CLI,但是錯誤是什麼?如果您將'&ptr'強制轉換爲'void **',會有幫助嗎? –

回答

1

這是一個out參數,不是真的ref,正確

void InitDB_clr(IntPtr %handle) 
{ 
pin_ptr<IntPtr> ptr = handle.ToPointer(); 
InitDB(&ptr); 
} 

錯誤消息?

嘗試

void InitDB_clr(IntPtr% handle) 
{ 
    void* ptr /* = handle.ToPointer() */; 
    InitDB(&ptr); 
    handle = IntPtr(ptr); 
} 

取消對初始化,如果它需要輸入/輸出。

+0

有了上面的代碼,我得到以下錯誤,當我編譯C++/CLI項目:錯誤C2440:「=」:不能從轉換「系統:: IntPtr的^」到「系統:: IntPtr的」 –

+0

@KSingh:唐」使用'gcnew'。順便說一句,這已經回答了在MSDN論壇,在那裏[你問同樣的問題(http://social.msdn.microsoft.com/Forums/en-US/vclanguage/thread/fdb13eb5-f6bd-4710-aadd -ebc898992bf9)。 – ildjarn

+0

@ildjarn:謝謝..我交叉張貼在stackoverflow和MSDN論壇上。而感謝你的幫助,現在的工作:) –

0

你可以使用C#在不安全的情況下,並使用

unsafe void InitDB_cs(IntPtr** handle); 
+0

我不想在C#中有指針/不安全的代碼。這是C++/CLI管理的原因之一,它將具有C#的所有功能並在內部與C DLL進行交互。 –