c# - C++/CLI:在 C#.NET 应用程序中返回对非托管对象的引用
问题描述
我正在使用 C++/CLI 将一些功能从本机 C++ dll 包装到 .NET。我的一个本地类(UA 类)有一个方法可以返回对另一个本地类/对象(UB 类)的引用。我已将这两个类包装在我的 C++/CLI 项目中,如下所示:
//Unmanaged classes
class UA
{
public:
A(int x) : m_x(x) {}
int m_x;
};
class UB
{
public:
UB() : a(1) {}
UA& get_A(){return a;}
protected:
UA a;
};
// managed classes /CLI
public ref class A
{
internal:
A(UA* a) : m_ptr(a) {}
public:
A() : m_ptr(new UA(1)) {}
~A()
{
this->!A();
}
!A()
{
if (m_ptr != nullptr)
{
delete m_ptr;
}
}
private:
UA* m_ptr;
};
public ref class B
{
public:
B() : m_ptr(new UB()) {}
A^ get_A(){return gcnew A(&m_ptr->get_A())}
~B()
{
this->!B();
}
!B()
{
if (m_ptr != nullptr)
{
delete m_ptr;
}
}
private:
UB* m_ptr;
};
/clr
上面用;编译 但是,在 C#.NET 应用程序中进行测试时,我得到一个调试断言错误。
// C#.NET app
B b = new B();
A = b.get_A();
此错误发生在(!A())
托管包装的终结器中class A
。特别是,当 GC 试图删除本机指针时会引发它。我想这只是为什么我没有用 new 关键字创建这个实例的原因。您认为在本机 C++ 中使用复制构造函数然后使用 new 关键字创建托管包装类会更好吗?
例如:
//Unmanaged classes
class UA
{
public:
A(int x) : m_x(x) {}
A(const A& a)
{
m_x = a.m_x;
}
int m_x;
};
然后托管的 A 和 B 包装器将是:
// managed classes /CLI
public ref class A
{
internal:
A(UA* a) : m_ptr(a) {}
public:
A() : m_ptr(new UA(1)) {}
~A()
{
this->!A();
}
!A()
{
if (m_ptr != nullptr)
{
delete m_ptr;
}
}
private:
UA* m_ptr;
};
public ref class B
{
public:
B() : m_ptr(new B()) {}
A^ get_A(){return gcnew A(new UA(&m_ptr->get_A()))}
~B()
{
this->!B();
}
!B()
{
if (m_ptr != nullptr)
{
delete m_ptr;
}
}
private:
UB* m_ptr;
};
是否有任何不同的方法可以在 C# 中返回对非托管对象的引用?抱歉,如果我做错了什么,我在 C++/CLI 方面的经验非常少。我也看过这个帖子;但是,似乎接受的答案提出了我首先实施的解决方案。我感谢任何帮助/建议。
解决方案
这只是因为当您调用时b.get_A()
,this 会调用您的内部构造函数,该构造函数A(UA* a) : m_ptr(a) {}
只存储指向a
类型对象字段的指针UB
。然后,析构函数将尝试删除这个不能工作的指针。
这与 C++/CLI 无关,只是与分配和删除对称。在这种情况下,只需删除A()
执行分配的公共构造函数以及那些析构函数,它就会起作用。
推荐阅读
- excel - 使用 VBA 将 PPT 保存为 pdf
- amazon-web-services - 使用 boto3 通过 Kinesis Firehose 将数据发送到 Amazon S3 时访问被拒绝
- r - 如果存在分隔符,如何拆分列,否则使用 R 保留相同的值
- php - 使用 php/ajax 从数据库中删除项目
- c# - 如何将 AccessToken 存储到 Cookie 并使用它们为 Asp.net Web 应用程序(非 MVC)调用 Graph API
- javascript - Cropper.js 如何在没有上传表单的情况下裁剪图像
- android - 如何防止主题更改时屏幕闪烁?
- java - 这是因为内存泄漏吗?
- python - 无法在 python 中构造 struct.pack 连接名称
- axios - Vuejs-从 Promise-Request 到 Axios 的下载文件迁移-第一个参数必须是字符串、Buffer、ArrayBuffer、Array 或类似数组的对象