【问题标题】:P/Invoke C++ template<T> method from C#来自 C# 的 P/Invoke C++ 模板<T> 方法
【发布时间】:2012-12-29 18:30:44
【问题描述】:

我已经在 C++ 中定义了用于外部调用的函数:

template<typename T>
void __declspec(dllexport) SwapMe(T *fisrt, T *second)
{
    std::cout << typeid(T).name() << std::endl;

    T temp = *first;
    *first = *second;
    *second = temp;
}

我想在 C# 程序中使用它。我试过这样:

unsafe class Program
{
    [DllImport("lib1.dll", EntryPoint = "SwapMe")]
    static extern void SwapMe<T>(T first, T second);

    ...
}

但是,我收到这样的错误:

泛型方法或泛型类中的方法是内部调用、PInvoke 或在 COM 导入类中定义。

似乎,C# 中的 Generic 是托管类型,并且在 C++ 中使用非托管模板的架构与它完全不同。

如何在我的 C# 程序中使用模板方法?

【问题讨论】:

  • 不可能,模板没有外部链接。您可以获得的最接近的是使用 generic 关键字的 C++/CLI 代码。
  • @HansPassant 是什么意思?请给我解释一下!我可以在 C++ 中使用一些二进制序列化(或类似的东西......) 手动准备外部链接吗?谢谢!
  • 意思是完全,完全,不可能,不可能。试图让它工作没有意义,它不会工作。

标签: c# c++ templates generics pinvoke


【解决方案1】:

C++ 编译器不会将模板函数烧录到二进制文件中。只发布专门的版本。 C++ 编译器在逻辑上克隆模板定义并将T 替换为所需的任何具体类型。

这意味着您必须创建一个专门的包装器:

void __declspec(dllexport) SwapMe(int *fisrt, int *second) { //example
{ SwapMe(first, second); }

你可以从C#调用这个,但是你不能调用模板版本。

C++ 模板和 C# 泛型的工作方式非常不同。

【讨论】:

  • 似乎是,它是 C++ 模板和 C# 泛型之间的主要区别之一。但是 C++/CLI 如何使用它呢?
  • @OlegOrlov C++/CLI 可能永远不会通过设置限制来违反规则。我没有资格肯定地回答,但我的猜测是你不能用泛型参数调用模板函数。它可能会导致编译器错误。
  • 但是 必须有一些默认结构。是的,C++ 确实取代了它,但目前,当它没有被取代时,它也必须有一些结构。替换前的T是什么结构?
  • @OlegOrlov T 真的没有结构。你怎么解释你可以写T x, y; return x == y;?并非每种类型都具有可比性,而具有可比性的类型可能会完全不同。出于这个原因,这不适用于泛型(但在 C++ 中有效)。这只有效,因为 T 在编译时被替换为精确的类型。
  • ahhh... 而泛型是一个真正的未定义结构,它真正存在于运行时,并且在运行时通过反射获得结果......为什么 C++ 没有这样的东西? (不知道C++ 11 版本,C++ 11 不支持泛型吗?)
【解决方案2】:

为了补充以上内容,我们最近通过 T4 (TextTransform.exe) 为 C++ 中的包装器生成模板。

为此,我们在 C++ 项目中包含了一个 T4 文件,并且针对类型 args 的每种组合,围绕 C++ 模板方法生成了一个包装器方法。然后导出包装器方法。

最后,我们在 C# 中做了同样的事情,使用 T4 为导出的方法生成一个通用包装器。通过这种方式,您可以在 .NET 泛型和 C++ 模板之间架起一座桥梁,同时充分利用 C++ 模板的强大功能

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多