用C/C++编写DLL以实现.Net互操作性

Mar*_*lle 12 c# interop native

在我的C#应用​​程序中,我想在C中编写一部分代码.我计划编写一个可与​​.Net互操作的DLL.我怎样才能做到这一点?

Ben*_*igt 20

基本上有三种正确的方法:

  • 使用C++/CLI.如果此DLL仅由.NET使用,这是最佳方法.
  • 使用" extern "C""兼容的API,如Windows API本身.这是最便携的,但对于您的调用者而言,使用类模型来表示对象并不方便.
    • 如果您真的打算用ANSI C(而不是C++)编写,这是最好的选择.
    • 对于此路径,您将函数编写为 extern "C" returntype __stdcall __declspec(dllexport) func(params) { ... }
    • 您还应该使用"caller-provide-the-buffer"内存模型,而不是返回库中分配的缓冲区.在您需要为内部状态分配内存的情况下,调用者应将其视为不透明句柄,并且应为调用者提供访问器函数以提取数据.在任何情况下都不应该要求调用者释放在库中分配的内存,但是调用者可以要求库进行重新分配.
  • 使用COM或类似COM的API.在这里,您返回(通常通过out参数)指向接口的指针,该接口是具有纯虚函数,没有非虚函数且没有数据的类.
    • 实现是从这个抽象接口派生的具体类,它们可以有丰富的数据和辅助函数,因为这不会影响二进制接口.
    • 这在图书馆中工作量很大,但非常便携,便于消费者使用.

并且有一件事绝对不要做:

  • 用于__declspec(dllexport)C++类.

编辑:我还想解释选项#2的一些好的做法,它们将最大限度地提高可移植性,并使原生C/C++部分也可以从非托管应用程序中使用.

使用宏可以使这更容易,通常的做法是:

在头文件中,所有函数声明都是这样的

MYPROJECTAPI(returntype) PublicFunc(params);
Run Code Online (Sandbox Code Playgroud)

在您的项目中,定义是

#define MYPROJECTAPI(returntype) \
                   extern "C" returntype __stdcall __declspec(dllexport)
Run Code Online (Sandbox Code Playgroud)

在消费者项目中

#define MYPROJECTAPI(returntype) \
                   extern "C" returntype __stdcall __declspec(dllimport)
Run Code Online (Sandbox Code Playgroud)

然后你可以为不使用的其他编译器(如gcc)定义宏__declspec.

完整的解决方案看起来像(在公共头文件中myproject.h):

#if _WIN32
#  if BUILDMYPROJECT
#    define MYPROJECTAPI(returntype) \
         extern "C" returntype __stdcall __declspec(dllexport)
#  else
#    define MYPROJECTAPI(returntype) \
         extern "C" returntype __stdcall __declspec(dllimport)
#  endif
#else
#  define MYPROJECTAPI(returntype) extern "C" returntype
#endif
Run Code Online (Sandbox Code Playgroud)

然后BUILDMYPROJECT在构建myproject.dll时将导致您的Visual C++项目被定义