【问题标题】:How do I use a C++ library from C# and .NET?如何使用来自 C# 和 .NET 的 C++ 库?
【发布时间】:2010-08-26 20:18:24
【问题描述】:

我的问题与 DLL 如何导出 C++ 类和通用方法(没有 C# 并行的 C++ 语言功能)密切相关。

我相信您可以通过引用 DLL 并使用 DLLImport 从 C# 调用 extern "C" 块内的函数。但是你能实例化一个模板化的 C++ 类型吗?如果 C++ 类型在 C# 中不支持 somethin' crazy 怎么办? C# specification 是否有 RFC 或相关部分?

谢谢...

编辑:我现在偶然发现了P/Invoke,这应该很有价值,但我仍在寻找有关此的规范或标准。

【问题讨论】:

    标签: c# .net c++ dll


    【解决方案1】:

    明智的做法是使用托管 c++ 访问非托管 c++ 并编译成程序集。

    【讨论】:

    • 关于这方面的更多信息?我是 Windows 编程新手,习惯了 Unix、静态链接和 Makefiles……如何在 VS2010 中使用 C++ 创建托管 DLL 或非托管 DLL?
    • @robert 上面的链接暴露了非常古老的过时托管 C++ 语法,例如,__gc 在现代语法中变为 ref
    • 检查底部的这个链接,语法之间的差异显示了我很好的例子:visualcplusdotnet.com/visualcplusdotnet18b.html
    【解决方案2】:

    我相信你可以调用函数 在 C# 的外部“C”块内 只是引用 DLL。

    错了,您必须使用DllImport 或所谓的PInvoke(平台调用)从托管代码调用本机C 函数。引用仅适用于 .NET 程序集或带有 automatically generated interop dll 的 COM。

    在 C# 中使用 C++ 变成了一场真正的噩梦,因为名称混乱等等。

    如果可以的话,您可以将托管 C++ Dll 编译为包装器,以使这两个世界相遇。这还有一个优点,您可以将程序集标记为ComVisible,从而使其可用于大量能够处理 COM 的工具。

    另一种方法是围绕 C++ API 编写 C 包装器,这可能既乏味又丑陋。

    编辑:

    帮助决定使用哪种方法:

    • 1) 您有一个本机 C dll
      • 警告:如果您使用 Managed C++ 中的 .lib,则 dll 不是真正动态链接的,并且无法用更新的兼容版本的简单插入替换。
      • 首选:使用任何 .NET 语言的 P/Invoke(可以直接替换)

    • 2) 你有一个本地 C++ dll
      • 不要使用 P/Invoke,这是一场真正的噩梦(因为名称混乱等)
      • 首选:使用托管 C++ 构建包装器 .NET dll,仅当您的编译器与用于编译本机 dll 的编译器兼容时才有效。
      • 如果本机 DLL 是使用可用于托管 C++(编译器 C)的不兼容编译器(编译器 A)构建的,那么我建议围绕本机 C++ 构建(使用相同的编译器 A)C 包装器dll。然后使用 P/Invoke 方法来使用这个包装器 C dll,如 1) 中所述

    【讨论】:

    • 感谢您的更正。你能用 C++ 创建一个 .NET 程序集吗?
    • 是的,您可以,但使用托管 C++,它实际上不是 C++,但如果您碰巧使用与生成您正在使用的纯 C++ dll 的编译器相同的编译器,您可以链接到本机 C++ Dll。
    • 不,真的不是:-)。但真正动态链接来自 .NET 的第 3 方 C dll 的好方法。使用托管 C++ 很容易用原生东西污染纯 .NET 世界。
    【解决方案3】:

    就 C# 而言,DLL 在内部执行的操作无关紧要。请记住,在模板实例化之前,C++ 模板不会生成任何代码。如果模板只是在 DLL 头文件中的某处定义,那么 DLL 中将不会为该模板生成任何代码。另一方面,如果 DLL 显式实例化并导出一些模板类型,那么理论上您可以从 C# 中调用它们。

    您必须克服两个问题。首先是 C++ 编译器会破坏它们的方法名称,因此您必须弄清楚 PInvoke 的正确名称是什么。第二个问题是无法直接在 C# 中创建 CRT 对象。您必须定义一些工厂方法并将其导出。

    坦率地说,我认为这比它的价值更麻烦。您最好为 DLL 创建一个 C 风格的 API 并从 C# 调用这些函数。在内部,这些函数可以创建和操作相关的 C++ 对象。

    【讨论】:

    • 好吧,这听起来很痛苦。创建 C API 是一个公平的解决方案,但我很惊讶没有更灵活的互操作机制......
    • 互操作机制必须为任何编译器处理所有可能的重整方案,因为对此没有标准(这是一个很大的痛苦)并且编组/解编组并非易事。在 COM 的情况下,一切都在接口中指定,并且类型在大小和对齐方面都得到了很好的定义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多