C++/CLI wrapper for C dll
So I have this C .dll source code which I want to use in my C# application. Instead of doing bunch of DllImports I've decided to write a wrapper for it in C++/CLI.
My C function takes a pointer to a struct with 4 callback functions in it:
typedef struct
{
PFN_IN readFp;
PFN_OUT writeFp;
}OPEN_ARGS;
C++/CLI shares the same .h file, therefore uses the same typedef.
C# code has it's own definition of this structure and delegates for CBs, because I can't attach .h to C# project.
[UnmanagedFunctionPoin开发者_如何学JAVAter(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;
};
So, when I add my C++/CLI dll explicitly to C# project references, the compliler wouldn't accept calls to C++/CLI functions saying
"Error 2 Argument 2: cannot convert from 'WrapperTest.Program.OPEN_ARGS' to 'SAR_OPEN_ARGS'"
But if I include the C++/CLI dll implicitly like that
[DllImport("Wrapper.dll", CharSet = CharSet.Auto, EntryPoint = "?CLIOpen@@YAHHUOPEN_ARGS@@@Z")]
public static extern int CLIOpen(int a, OPEN_ARGS args);
It will work just fine.
So is there a way to tell C# compiler to ignore this type cast error, or may be other way to wrap C code functions?
EDIT: cleaned up variable names for better readabiltiy
What if you did this another way. Since you have a C++/CLI DLL handling interop duties between the C DLL and the C# assembly, you could expose an equivalent API, only using more .NET-like concepts.
For example, instead of exposing the struct with function pointers, you could expose a class that has three events. The C# assembly would add handlers for those events. Inside the C++ DLL, it would use the function pointers that the C DLL expects, but their implementation would fire the .NET events that the C# assembly is handling.
This would provide a much better experience using the DLL on the C# side, and likely get rid of the interop compiler errors that you're encountering.
Please consider using SWIG to generate the wrapper code for all your pinvoke.
http://www.swig.org/Doc1.3/CSharp.html
So for managed C++, you can use the #pragma managed/unmanaged compiler directives instead of pInvoke, which it looks like you are using. Then you can compile managed and native code together into the same assembly, even the same CPP file.
Then you could do something like:
#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 );
}
};
精彩评论