2011-06-17 48 views
0

因此,我有這個C .dll源代碼,我想在我的C#應用​​程序中使用它。我決定在C++/CLI中爲它編寫一個包裝器,而不是做大量的DllImport。用於C dll的C++/CLI包裝

我的C函數需要一個指針到一個結構與4個回調函數在它:

typedef struct 
{ 
PFN_IN readFp; 
PFN_OUT writeFp; 
}OPEN_ARGS; 

C++/CLI共享相同的h文件,因此使用相同的類型定義。

C#代碼有它自己定義的這個結構和代理CB,因爲我不能將.h添加到C#項目中。

[UnmanagedFunctionPointer(CallingConvention.Cdecl)] 
    public delegate Int32 PFN_OUT(IntPtr arg, IntPtr pSrc, Int32 len); 

    [StructLayout(LayoutKind.Sequential)] 
    public struct OPEN_ARGS 
    { 
     public PFN_IN readFp; 
     public PFN_OUT writeFp; 
    }; 

所以,當我加入我的C++/CLI DLL明確到C#項目引用,該compliler不會接受以C++/CLI函數的調用說

"Error 2 Argument 2: cannot convert from 'WrapperTest.Program.OPEN_ARGS' to 'SAR_OPEN_ARGS'" 

但是,如果我包括C++/CLI dll隱含的那樣

[DllImport("Wrapper.dll", CharSet = CharSet.Auto, EntryPoint = "[email protected]@[email protected]@@Z")] 
public static extern int CLIOpen(int a, OPEN_ARGS args); 

它會工作得很好。

那麼有沒有辦法告訴C#編譯器忽略這種類型轉換錯誤,或者可能是其他方式來包裝C代碼函數?

編輯:清理變量名更好readabiltiy

回答

4

,如果你做了什麼這個法子。既然你有一個C++/CLI DLL處理C DLL和C#程序集之間的交互操作,你可以公開一個等效的API,只使用更多的類似.NET的概念。

例如,您可以公開具有三個事件的類,而不是將結構暴露給函數指針。 C#程序集將爲這些事件添加處理程序。在C++ DLL裏面,它會使用C DLL期望的函數指針,但是它們的實現會觸發C#程序集正在處理的.NET事件。

這將提供更好的使用C#端DLL的經驗,並可能擺脫您遇到的互操作編譯器錯誤。

+0

感謝您的建議。聽起來是一個好主意。 ps。由於某種原因,我不能upvote你的帖子:o – fl0sT

0

因此,對於託管的C++,您可以使用#pragma managed/unmanaged編譯器指令而不是pInvoke,它看起來像您正在使用的。然後,您可以將託管代碼和本地代碼一起編譯到相同的程序集中,即使是相同的CPP文件。

然後,你可以這樣做:

#pragma managed 
// include your native headers here 
#include "foo.h" // whatever you call it. 

#using <System.dll> // what ever else you need here... 

// Have to wrap a function in a class, since .NET doesn't allow free standing functions. 
public ref class foo 
{ 
public static int sarCLIOpen(int a, SARWrapperTest::Program::SAR_OPEN_ARGS args) 
{ 
// do something to convert your managed args to native args. 
::SAR_OPEN_ARGS native_args = ... 
// then call your native function 
return sarCLIOpen(a, native_args); 
} 

}; 
+0

這正是我正在做的,如果我正確地理解你。我有我的.c和.h源代碼來自C++/CLI項目中包含的原始C dll。我正在編譯這個項目作爲另一個DLL,我想在我的C#應用​​程序中使用它。 – fl0sT

+0

請注意,雖然我的託管方法的函數簽名。它需要一個受管理的SAR_OPEN_ARGS ...這是你在做什麼?您不能在託管參數列表中公開本機類型,這看起來像根據上面的編譯器錯誤所做的。 –

+0

是的,我認爲這是一個有效的建議,儘管在包裝器中聲明WrapperTest :: Program :: OPEN_ARGS而不是在C#應用程序中調用它是有意義的,以避免緊密耦合。 感謝您的意見。 – fl0sT