将非托管 c++ 类库暴露给 c#
Posted
技术标签:
【中文标题】将非托管 c++ 类库暴露给 c#【英文标题】:expose unmanaged c++ class library to c# 【发布时间】:2009-04-24 08:34:11 【问题描述】:事实上,我有两个未损坏的 c++ 库,其中一个使用了另一个。两者都很大,所以重写不是我的选择。
我阅读了一些关于创建一个包含非托管代码的托管 c++ 库的内容。但我真的不知道如何开始,以及如何将所有这些东西组合到一个项目中......
是否有任何分步指南或易于理解的示例说明如何执行此操作?
TIA
【问题讨论】:
已经在这里回复***.com/questions/761930/… 以及许多其他帖子;这是最近很常见的问题。 【参考方案1】:您可以考虑使用 ATL 为您的 C++ 代码编写一个 COM 包装器。我在blog post 中展示了如何做到这一点。这就是微软公开他们用 C++ 编写的功能(例如 Windows 7 库功能)的方式。 COM 很容易被 .NET/C# 使用(参见this post)。如果你走这条路,如果你不需要与其他人共享你的包装器,你可以考虑registration free COM。
【讨论】:
【参考方案2】:您可以在同一个项目中编写托管和非托管 C++。因此,您可以在 Managed C++ 中编写一个包装器来调用您的本机 c++ 类等。然后在 C# 中,您的托管 C++ 类将与任何其他 .net 引用一样出现。在这种情况下无需使用 P/Invoke。
【讨论】:
【参考方案3】:您有两种选择,一种称为 ijw “它可以工作”,您可以在其中编写托管 c++ 并调用非托管 c++。另一个选项需要使用 pinvoke。
如果你使用 pinvoke,你会得到类似的东西
C#
somefunction("str1", "str2", "str3", "str4");
[DllImport(@"myproj.dll", EntryPoint = "somefunction")]
public static extern IntPtr SomeFunction([MarshalAs(UnmanagedType.LPWStr)]string jarg1, [MarshalAs(UnmanagedType.LPWStr)]string jarg2, [MarshalAs(UnmanagedType.LPWStr)]string jarg3, [MarshalAs(UnmanagedType.LPWStr)]string jarg4);
c++
extern "C" __declspec(dllexport) void* __stdcall somefunction(wchar_t * jarg1, wchar_t * jarg2, wchar_t * jarg3, wchar_t * jarg4)
//do some stuff with strings
如果你使用 SWIG,swig 会尝试自动生成上面的代码,但它是一个苛刻的大师。
我曾经使用过托管 c++,但我不记得我是怎么想的了。
【讨论】:
【参考方案4】:我认为这取决于您实际需要公开多少库功能。
我不知道如何创建托管 C++ 包装器,但我个人使用了另外两种方法来解决这个问题:
使用 SWIG 为您的 C++ 类自动生成 C# PInvoke 包装器。这种方法很有效,但只有在您需要公开 很多 的类和成员时才真正值得。根据我的经验,自动生成的代码仍然需要手动进行一些调整。
仅针对您需要的功能编写非托管 C 包装器,将它们从 DLL 中导出,并手动编码您需要导入 C# 的少数 PInvoke 包装器。我发现这在某些情况下更合适,例如有一个大型 C++ 类库可以执行不同类型的图像文件转换,但您真正想要公开的只是一个函数DoTheConversion(LPWSTR inputFile)
。我的 C# 程序不需要了解底层类库的所有复杂性。
【讨论】:
【参考方案5】:阅读其中一些文章可能是一个开始 - 这是一个相当广泛的主题,并且没有“完美”的方法:
http://www.ondotnet.com/pub/a/dotnet/2004/03/29/mcpp_part3.html http://www.codeguru.com/cpp/cpp/cpp_managed/interop/article.php/c6867
这些方法都没有使用 p/invoke,这是我们在我工作的项目中使用的一种方法,我们需要连接一个非常老旧的 c++ 服务库。
【讨论】:
以上是关于将非托管 c++ 类库暴露给 c#的主要内容,如果未能解决你的问题,请参考以下文章