当函数 returns 指针指向抽象 class 时,将 "C++ dll" 包装在 "C++/CLI" 中
Wrapping "C++ dll" in "C++/CLI" when function returns pointer to abstract class
我有 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 管理 class:
#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# 应用程序中使用 ManagedClI class,类似于:
CLIWrapper.ManagedClI object = new CLIWrapper.ManagedClI();
object.Create();
object.SomeFunction(); // <- this causes an error
object.SomeFunction()
导致错误:在调用 cl1->method()
时试图读取或写入受保护的内存。
但同时 cl1->method()
在 Object.Create()
.
中正常工作
我认为我在包装时做错了什么 Create_function()
。
谁能推荐一下?
您的 Library loader
不仅仅是一个加载器。它是保持 DLL 加载的 CLI 对象。当对它的最后一次引用消失并被清理时,DLL 被卸载。
抽象 class 的虚函数 table 存在于该 DLL 中,它指向的函数也是如此。当 DLL 被卸载时,那个虚函数 table 变得无效,并且试图调用该方法将是未定义的行为。
要初步解决此问题,请将 Library
对象存储在 ManagedClI
class 中,而不是作为局部变量。
我有 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 管理 class:
#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# 应用程序中使用 ManagedClI class,类似于:
CLIWrapper.ManagedClI object = new CLIWrapper.ManagedClI();
object.Create();
object.SomeFunction(); // <- this causes an error
object.SomeFunction()
导致错误:在调用 cl1->method()
时试图读取或写入受保护的内存。
但同时 cl1->method()
在 Object.Create()
.
我认为我在包装时做错了什么 Create_function()
。
谁能推荐一下?
您的 Library loader
不仅仅是一个加载器。它是保持 DLL 加载的 CLI 对象。当对它的最后一次引用消失并被清理时,DLL 被卸载。
抽象 class 的虚函数 table 存在于该 DLL 中,它指向的函数也是如此。当 DLL 被卸载时,那个虚函数 table 变得无效,并且试图调用该方法将是未定义的行为。
要初步解决此问题,请将 Library
对象存储在 ManagedClI
class 中,而不是作为局部变量。