【发布时间】:2015-03-16 13:20:47
【问题描述】:
我有 c++ dll: UnmanagedCode.h 看起来像:
#include "stdafx.h"
struct Class1
{
public: virtual void method() = 0;
};
extern "C" __declspec(dllimport) Class1* Create_function();
UnmanagedCode.cpp 看起来像:
#include "stdafx.h"
#include "UnmanagedCode.h"
class Class2 : Class1
{
public: void method(){}
};
Class1* Create_function()
{
Class2* c2 = new Class2(); // I don't care about free memory for this example
Class1* c1 = (Class1*)c2;
return c1;
};
我有 c++/cli 托管类:
#include "Library.h"
#include "UnmanagedCode.h"
typedef Class1* (*Createfunction)();
namespace CLIWrapper
{
public ref class ManagedClI
{
private:
Class1* cl1;
public:
ManagedClI(){}
void Create()
{
//some usual routine for loading c++ library with Library class
String ^path = "path to the library.dll"; // just to show
using System::Runtime::InteropServices::Marshal;
const char* cpath = (const char*)(Marshal::StringToHGlobalAnsi(path)).ToPointer();
Library loader;
loader.load((string)cpath, false);
Marshal::FreeHGlobal(System::IntPtr((void*)cpath));
Createfunction hDet = (Createfunction)loader.getProcAddress("Create_function");
cl1 = hDet();
cl1->method(); // if I call cl1->method() here it works perfect!!
}
void SomeFunction()
{
cl1->method(); //but if I call cl1->method() here it throws an error!!!
}
};
}
我在我的 c# 应用程序中使用 ManagedCI 类,类似于:
CLIWrapper.ManagedClI object = new CLIWrapper.ManagedClI();
object.Create();
object.SomeFunction(); // <- this causes an error
object.SomeFunction() 导致错误:在调用 cl1->method() 时尝试读取或写入受保护的内存。
但同时cl1->method() 正常工作在Object.Create()。
我认为我在包装 Create_function() 时做错了什么。
任何人都可以提出一些建议吗?
【问题讨论】:
-
一个猜测(我不是 C++/cli C++ C# 互操作专家),但我要调查的是,如果
loader超出范围会导致Library对象卸载 dll。哪个卸载虚拟功能表,并导致您的问题?它至少可以解释症状,并且很容易检查:将Library对象存储在您的ManagedCLI类中而不是本地。 -
@Yakk 你是对的!非常感谢!
-
另外,永远不要使用
Marshal::StringToHGlobalAnsi。 C++/CLI 带有marshal_as<std::string>帮助模板,它的工作效率提高了一千倍。 -
@BenVoigt 实际上这只是举例,但无论如何,谢谢 =) 但 Loader 是真实的。
-
本机代码永远不需要太多帮助来破坏堆,当它爆炸时向我们展示堆栈跟踪对于停止猜测非常重要。您在代码中犯了一个错误,C++/CLI 编译器无法判断这些声明是针对本机代码的,并且使用 __cdecl 调用约定。您需要用#pragma managed(push, off) 和#pragma managed(pop) 包装#include 和typedef。
标签: c# visual-c++ c++-cli clr wrapper