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

标签 c# interop native

在我的 C# 应用程序中,我想用 C 编写一部分代码。 我计划编写一个 DLL 女巫,可以与 .Net 互操作。 我该怎么做?

最佳答案

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

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

有一件事绝对不能做:

  • 在 C++ 类上使用 __declspec(dllexport)

编辑:我还想解释选项 #2 的一些良好实践,这将最大限度地提高可移植性,并使 native C/C++ 部分也可从非托管应用程序中使用。

您可以使用宏来简化此操作,通常的做法是:

在你的头文件中,所有的函数声明看起来像

MYPROJECTAPI(returntype) PublicFunc(params);

在你的项目中,定义是

#define MYPROJECTAPI(returntype) \
                   extern "C" returntype __stdcall __declspec(dllexport)

在消费者项目中

#define MYPROJECTAPI(returntype) \
                   extern "C" returntype __stdcall __declspec(dllimport)

然后您可以为其他不使用 __declspec 的编译器(例如 gcc)定义不同的宏。

完整的解决方案看起来像(在公共(public)头文件 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

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

关于c# - 使用 C/C++ 编写 DLL 以实现 .Net 互操作性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3726829/

相关文章:

c# - 与 nim 互操作返回包含 string/char* 成员的结构数组

ruby - 如何从 Ruby 调用 shell 命令

c++ - 从 Web C++ 下载文件(使用 winsock?)

c# - 通过读取 web.config 更改 Web 服务的 URL

c# - Mkdirs Xamarin 不适用于 Android 6.0

c# - Access 等同于 C# List<T> 的 VBA

java - 不同JNI调用的相同参数是否具有相同的值?

.net - 在 Powershell v3 中无需调用外部 EXE 即可确定 .NET 程序集是否为混合模式

c# - 是否有 "right"方法来抽象出我的代码?

c# - 通过电子邮件 IOS 发送带有图像的 HTML 文件