【问题标题】:Exporting a class which uses managed handles?导出使用托管句柄的类?
【发布时间】:2012-10-20 20:11:33
【问题描述】:

我正在尝试在 C++/CLI 中围绕 .Net 库创建一个本地包装器,以便常规 C++ 代码可以使用它。对于此示例,假设这是我要包装的 C# 代码:

class Foo
{
    public Bar GetBar() {...}
    public string SomeProperty { get; set; }
}

class Bar
{
    public void Baz() {...}
}

我基本上是在 C++/CLI(dll 项目)中大致尝试这样做:

class __declspec(dllexport) NativeFoo
{
public:
    NativeBar GetBar();
    std::string GetName();
    void SetName(const std::string &value);

private:
    Foo ^m_foo;
};

class __declspec(dllexport) NativeBar
{
    friend class NativeFoo;
public:
    void Baz();

private:
    Bar(Bar ^bar);

    Bar ^m_bar;
};

这样,一个 C++ 库可以链接到这个,使用 NativeFoo 就好像它是一个普通的 C++ 类一样。在内部,NativeFoo 将转换参数以将实现传递给 m_foo,将所有管理的内容编组回本地表示并将其返回给它的调用者...

但是,我遇到的问题是我不能拥有非托管类的托管成员:

error C3265: cannot declare a managed 'm_bar' in an unmanaged 'NativeFoo'

同样,我不能将 NativeFoo 标记为“ref”(本身就是一个托管类),因为这样我就不能导出它:

C3386: 'NativeFoo' : __declspec(dllexport)/__declspec(dllimport) cannot be applied to a managed type

在我的 C++ 对象中使用托管指针的正确方法是什么?

【问题讨论】:

  • 您可以使用 __declspec(dllexport) 导出托管函数,而不是类。一般来说,你忽略了一个先有鸡还是先有蛋的问题。有人将不得不加载 CLR,以便托管代码可以执行。 dllexport 指令创建一个处理该问题的存根。但这并不理想。您首先需要确定是创建调用本机代码的托管程序(简单)还是执行托管代码的本机程序(困难)。

标签: c++-cli


【解决方案1】:

您需要使用gcroot 在非托管类型上声明托管句柄。对于任何非托管类型,无论是否被 dllexported,您都需要它。

上面有一个MSDN page,上面有一些很好的信息和一些示例。

我相信你最终会得到这样的结果:

class __declspec(dllexport) NativeFoo
{
public:
    NativeBar GetBar();
    std::string GetName();
    void SetName(const std::string &value);

private:
    gcroot<Foo^> m_foo;
};

【讨论】:

  • 好答案。我从 gcroot 开始,后来发现了 auto_gcroot。即msclr::auto_gcroot&lt;Foo^&gt; m_foo; 记住与#include &lt;msclr/auto_gcroot.h&gt; 一起使用。
  • 这个答案的缺点是Foo必须声明为“ref class”,而原生C++头文件不能有该声明。
猜你喜欢
  • 2018-08-19
  • 1970-01-01
  • 2012-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多