在我的 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/