我一直在将一堆旧的C ++代码转换为C ++ / CLI代码,我想我已经将自己编写成了一个角落。
我的目标是获取一个非托管的c ++库和一堆头文件,并将其功能公开给C#解决方案。从在互联网上阅读,标准的方法是:
但是,我的场景并不复杂,所以我决定尝试在一个类中实现所有内容。我现在正在努力解决生成AccessViolationExceptions的特殊问题。
我的头文件如下所示:
public ref class ManagedClass
{
public:
ManagedClass();
void CreateUnmanagedObject(String^ param1);
void UseUnmanagedObject();
UnmanagedObject *myUnmanagedObject;
}
我的cpp文件如下所示:
void ManagedClass::CreateUnmanagedObject(String^ param1)
{
/* Convert params, use them in some way. */
/* capture the output of this library call to the pointer defined in ManagedClass.*/
myUnmanagedObject= &(LibrayObject.LibraryMethod1());
}
void ManagedClass::UseUnManagedObject()
{
/* This function will pass the Unmanaged object into
* a library function which will do some work on it.
*/
LibraryObject.LibraryMethod2(*myUnmanagedObject);
/* Whoops! System.AccessViolationException is thrown! */
}
有趣的是,如果我在LibraryMethod1之后立即在CreateUnmanagedObject中调用LibraryMethod2,它可以正常工作。但是在CreateUnmanagedObject退出之后,似乎myUnmanagedObject指向的内存丢失了。
任何人都可以看到发生这种情况的原因吗?
编辑:库声明如下所示:
UnmanagedObject LibraryMethod1();
void LibraryMethod2(UnmanagedObject ¶m);
答案 0 :(得分:1)
您是否没有获取临时变量的地址?如果
LibraryObject.LibraryMethod1()
返回某个值的副本,然后您将获取局部变量的地址,该变量超出了方法末尾的范围。之后使用该地址是未定义的行为,在这种情况下会导致访问冲突!
答案 1 :(得分:1)
不确定你的真正问题是什么,但看起来都错了。托管包装器应该是非托管包装的非常接近的传真。让我们从像这样的非托管声明开始工作:
class Unmanagedclass {
public:
Unmanagedclass(const char* arg) {}
void mumble() {}
};
然后你的包装应该像这样:
#pragma managed(push, off)
#include "unmanagedclass.h"
#pragma managed(pop)
using namespace System;
using namespace System::Runtime::InteropServices;
public ref class ManagedWrapper
{
Unmanagedclass* instance;
public:
ManagedWrapper(String^ arg) {
IntPtr mem = Marshal::StringToCoTaskMemAnsi(arg);
instance = new Unmanagedclass((char*)(void*)mem);
Marshal::FreeCoTaskMem(mem);
}
~ManagedWrapper() {
delete instance;
instance = 0;
}
!ManagedWrapper() {
delete instance;
}
void mumble() {
instance->mumble();
}
};
这里的方法是非托管类的实例是包装器中的指针。并且只需将托管方法调用委托给非托管方法。是的,有些带字符串的hokeypokey,如图所示。并确保当用户或垃圾收集器绕过它时,会删除此本机实例。
答案 2 :(得分:0)
您正在使用指向on-stack-temp变量的指针。纯粹的运气,如果你一个接一个地调用这些方法,就会指出一些东西。
经过多年的c#comfort,我用c ++编写了一些东西,并且必须告诉你,我现在有同样的问题。
简而言之 - 不要获取临时创建的地址并将其存储在指针中供以后使用。周期。