【发布时间】:2010-09-09 18:00:16
【问题描述】:
我想从我的 C# 代码中调用我的非托管 C++ 库。有哪些潜在的陷阱和需要采取的预防措施?感谢您的宝贵时间。
【问题讨论】:
标签: c# windows visual-c++ unmanaged
我想从我的 C# 代码中调用我的非托管 C++ 库。有哪些潜在的陷阱和需要采取的预防措施?感谢您的宝贵时间。
【问题讨论】:
标签: c# windows visual-c++ unmanaged
您可以采用多种方法 - 一种是,您可以更新非托管 C++ 库,使其周围有托管 C++ 扩展包装器,并让 C# 直接利用这些类。这有点费时,但它为遗留非托管代码提供了一个很好的桥梁。但请注意,托管 C++ 扩展有时难以自行导航,因为其语法与非托管 C++ 相似,但足够接近,训练有素的眼睛将能够看到差异。
另一条途径是让您的非管理 C++ 实现 COM 类,并让 C# 通过自动生成的互操作程序集使用它。如果您对 COM 有足够的了解,这种方法会更容易。
希望这会有所帮助。
【讨论】:
这个问题太笼统了。唯一合理的答案是 P/Invoke,但这有点像说,如果你想为 Windows 编程,你需要了解 Win32 API。
关于 P/Invoke (http://www.amazon.com/NET-COM-Complete-Interoperability-Guide/dp/067232170X) 的几乎整本书都写过,当然还有整个网站:http://www.pinvoke.net/。
【讨论】:
您正在描述 P/Invoke。这意味着您的 C++ 库需要通过 DLL 接口公开自己,并且该接口需要足够简单,以便通过调用属性向 P/Invoke 描述。当托管代码调用非托管世界时,必须对参数进行编组,因此似乎可能会对性能造成轻微影响,但您必须进行一些测试以查看编组是否重要。
【讨论】:
最简单的开始方法是确保所有 C++ 功能都公开为“C”风格的函数。确保将函数声明为 _stdcall。
extern "C" __declspec(dllexport) int _stdcall Foo(int a)
确保你得到正确的编组,尤其是指针和 wchar_t * 之类的东西。如果你弄错了,可能很难调试。
从任一侧调试它,但不能同时调试。在调试混合原生和托管时,调试器会变得非常慢。一次调试一侧可以节省大量时间。
更具体需要一个更具体的问题。
【讨论】:
您还可以通过 P/Invoke 调用非托管代码。如果您的代码当前不使用 COM,这可能会更容易。如果你走这条路,我想你可能需要使用“C”绑定在你的代码中编写一些特定的导出点。
根据我的经验,您需要注意的最重要的事情可能是缺乏确定性垃圾收集意味着您的析构函数不会运行,而您之前可能认为它们会运行。您需要牢记这一点,并使用 IDisposable 或其他方法来确保您的托管代码在您需要时被清理。
【讨论】:
当然,如果您将代码打包为带有外部入口点的 DLL,那么总会有 PInvoke。没有一个选项是无痛的。它们取决于 a) 你在编写 COM 或托管 C 包装器方面的技能 b) 在 PInvoke 中碰巧你的手臂。
【讨论】:
我会看看swig,我们使用它对我们的项目有很好的效果,以便将我们的 C++ API 暴露给其他语言平台。
这是一个维护良好的项目,它有效地围绕您的 C++ 库构建了一个瘦包装器,可以让 C# 等语言直接与您的本机代码进行通信 - 省去了您必须实现(和调试)胶合代码的麻烦。
【讨论】:
如果您想要一个好的 PInvoke 示例,您可以查看 PInvoke.net。它有如何调用大多数win api函数的示例。
您还可以使用本文中的工具Clr Inside Out: PInvoke 将您的 .h 文件转换为 c# 包装器。
【讨论】: