所以我有这个C .dll源代码,我想在我的C#应用程序中使用它。我决定用C ++ / CLI编写一个包装器,而不是做一堆DllImports。
My C函数接受一个指向结构的指针,其中包含4个回调函数:
typedef struct
{
PFN_IN readFp;
PFN_OUT writeFp;
}OPEN_ARGS;
C ++ / CLI共享相同的.h文件,因此使用相同的typedef。
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 = "?CLIOpen@@YAHHUOPEN_ARGS@@@Z")]
public static extern int CLIOpen(int a, OPEN_ARGS args);
它会正常工作。
那么有没有办法告诉C#编译器忽略这种类型转换错误,或者可能是其他方式来包装C代码函数?
编辑:清理变量名称以获得更好的可读性
答案 0 :(得分:4)
如果你这样做会怎么样?由于您有一个C ++ / CLI DLL来处理C DLL和C#程序集之间的互操作职责,因此您可以公开一个等效的API,只使用更多类似.NET的概念。
例如,您可以公开一个包含三个事件的类,而不是使用函数指针公开struct。 C#程序集将为这些事件添加处理程序。在C ++ DLL中,它将使用C DLL期望的函数指针,但它们的实现将触发C#程序集正在处理的.NET事件。
这将在C#端使用DLL提供更好的体验,并且可能摆脱您遇到的互操作编译器错误。
答案 1 :(得分:0)
请考虑使用SWIG为您的所有pinvoke生成包装代码。
答案 2 :(得分:0)
因此,对于托管C ++,您可以使用#pragma托管/非托管编译器指令而不是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 );
}
};