【发布时间】:2011-08-05 22:38:38
【问题描述】:
我正在尝试使用 VS2010 针对我只能访问头文件和 dll/lib 文件的 C++ API 编写 C++/CLI 包装器。
我遇到了将本机引用从本机代码冒泡备份到 C# 代码中的跟踪引用的问题。我得到一个 SystemAccessViolation。代码如下:
用于返回对创建以及修改 CustomObject 的引用的本机函数的非托管本机 C++ 标头:
class ManageCustomObject;
_declspec(dllimport) errorCode CreateCustomObject(CustomObject& customObject);
_declspec(dllimport) errorCode ModifyCustomObject(CustomObject& customObject);
关于 CustomObject 需要注意的重要一点是它只有私有构造函数:
CustomObject(const CustomObject&) { }
CustomObject& operator=(const CustomObject&) { return *this; }
现在,我的 C++/CLI 层方法如下所示:
public ref class WrapperManageCustomObject {
public:
errorCode WrapperCreateCustomObject(CustomObject% customObject)
{
return CreateCustomObject(customObject);
}
errorCode WrapperModifyCustomObject(CustomObject% customObject)
{
return ModifyCustomObject(customObject);
}
};
CustomObject 的包装器如下所示:
public class WrapperCustomObject : public CustomObject {
public:
WrapperCustomObject(const CustomObject&) {};
};
在 C# 中,代码如下:
WrapperCustomObject wrapperCustomObject;
WrapperManageCustomObject wrapperManageCustomObject = new WrapperManageCustomObject();
long result;
// this works great
result = wrapperManageCustomObject.CreateCustomObject(ref wrapperCustomObject);
// can utilize wrapperCustomObject here with other native functions no problem, so long as I don't try to modify it...
...
// this throws an AccessViolationException was unhandled message
// essentially I am modifying / returning a different native customObject (though I'm not 100% sure what it does as I do not have access to the code)
result = wrapperManageCustomObject.ModifyCustomObject(ref wrapperCustomObject);
正如您在我的 cmets 中看到的那样,尝试通过引用修改该对象会引发“AccessViolationException 未处理:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。”
现在,如果我从这个等式中消除 C# 和跟踪引用,并在 C++ 或 C++/CLI 中执行所有这些操作(只要不存在跟踪引用),就可以正常工作。我认为这与本机代码试图访问更新现在在托管区域中的引用有关。
有没有什么办法可以从本质上使这段代码在 C# 中“工作”?我知道,没有办法传递对 C# 的本机引用。
【问题讨论】:
-
如果
CustomObject有一个私有构造函数并且没有工厂函数,你应该如何在 C++ 领域创建一个CustomObject?您需要已经有一个CustomObject实例才能调用CreateCustomObject辅助函数。 -
你是如何编译的?您正在返回一个 native 对象指针,但 C# 代码将其视为 managed 包装器。是的,当你使用它时,它会很大。本机对象指针应该是包装器的私有成员。
-
Stu - 我也可以将这些作为“out”参数,但仅此而已。参考参数是 C# 的东西。
-
Hans - C++/CLI 允许跟踪引用。信不信由你,这确实有效。
-
Adam - 如果函数已经返回对一个的引用,您不必在 C++ 领域创建 CustomObject - 意思是,我假设我看不到的 .cpp 文件是创建实例的位置并举行。您只需要一个容器来保存该引用。即:自定义对象自定义对象;在调用该函数之前。
标签: c# c++ c++-cli pass-by-reference