【问题标题】:Wrapping managed with unmanaged interface使用非托管接口包装托管
【发布时间】:2011-11-14 19:25:26
【问题描述】:

我有一个暴露了一些接口的非托管库。用户可以实现接口并使用他们的自定义实现将它们粘贴到库中。

我想为这个库提供一个托管包装器。 用托管接口包装非托管接口很容易。但在我的情况下,我想支持各种接口的用户实现,这意味着我需要采用一个接口的托管实现并使用它的非托管对应物将其包装,然后再将其发送到库的非托管部分的深处。

我尝试了类似的方法:

class UnmanagedWrapper {
DoSomething() {m_clr.DoSomething();}
IManaged^ m_clr;
}

但是编译器正确地声称,我不能在非托管类中拥有托管成员。

我可以在这里做一些优雅的事情吗?

【问题讨论】:

  • 上下文不足。使用 gcroot 或 Marshal::GetFunctionPointerForDelegate()。

标签: c++ clr managed-c++


【解决方案1】:

当一个库是非托管的而托管语言使用这些库时,这里有一些解决方法的相关信息。

此信息的上下文是在 Visual Studio 中使用 GoogleTest 的一种方式:

Getting started with Google C++ Testing Framework

Visual C++ 用户的重要提示 如果您将测试放入 库和您的 main() 函数在不同的库中或在您的 .exe 文件,这些测试将不会运行。原因是 Visual 中的错误 C++。当您定义测试时,Google Test 会创建某些静态 对象来注册它们。这些对象没有被引用 其他地方,但他们的构造函数仍然应该运行。什么时候 Visual C++ 链接器发现库中的任何内容都没有被引用 其他地方它把图书馆扔了。你必须参考你的 带有来自主程序的测试的库,以防止链接器 丢弃它。这是如何做到的。在您的库代码中的某处 声明一个函数:

__declspec (dllexport) int PullInMyLibrary() { return 0; }

如果您将测试放在静态库(不是 DLL)中,那么 __declspec(dllexport) 就是

不需要。现在,在你的主程序中,编写一个调用 那个函数:

   int PullInMyLibrary(); 
   static int dummy = PullInMyLibrary();

这将 保持您的测试被引用,并使它们在 启动。

此外,如果您在静态库中定义测试,请添加 /OPT:NOREF 到您的主程序链接器选项。如果您使用 MSVC++ IDE, 转到您的 .exe 项目属性/配置 属性/链接器/优化并将引用设置设置为保留 未引用的数据 (/OPT:NOREF)。这将阻止 Visual C++ 链接器 从决赛中丢弃您的测试生成的单个符号 可执行文件。

不过,还有一个陷阱。如果您使用 Google Test 作为静态 库(这就是它在 gtest.vcproj 中定义的方式)您的测试必须 也驻留在静态库中。如果您必须将它们放在 DLL 中, 您还必须更改 Google Test 以构建到 DLL 中。否则 您的测试将无法正确运行或根本不会运行。一般 这里的结论是:让你的生活更轻松——不要把你的测试写在 图书馆!

【讨论】:

    【解决方案2】:

    也许 gcroot<> 就是你想要的:

    class UnmanagedWrapper {
        DoSomething() {m_clr.DoSomething();}
        gcroot<IManaged^> m_clr;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-30
      • 1970-01-01
      相关资源
      最近更新 更多