将应用程序API和数据暴露给DLL [英] Exposing application API and data to DLL
问题描述
我有一个dll插件,myDLL.cpp,它有以下代码:
#includemyDLL.h
#includeMainApp.h
class A {
public:
//注意:SomeType是在主应用程序代码中定义的。
A(SomeType * data):m_data {data}
void MemberFunc(){
//注意:do_something应该访问主应用程序中的数据。
m_data-> do_something();
}
private:
SomeType * m_data;
};
//导出函数
A * createInstance(SomeType * data){
return new A(data);
}
在主应用程序中,我有:
stc :: vector< int> IntArray;
类SomeType {
SomeType(){
IntArray.resize(1000);
}
void do_something(){
//操作IntArray的内容。
IntArray [rand()%IntArray.size()] = rand();
}
};
typedef A *(_ createInstance)(SomeType *);
void main(){
//加载Dll并获取createInstance()
_createInstance createInstance = LoadMyDLL();
SomeType someType;
A * a = createInstance(& someType);
a-> MemberFunc();
//释放A的实例并卸载DLL。
UnloadMyDLL(a);
}
dll代码现在可以使用主应用程序的API,不能访问正确的数据。当我在 m_data-> do_something();
上放置一个断点并输入方法调用,然后我看到 IntArray
为空。
我可以成功地运行你的例子而不会遇到你的问题: / p>
- 我假设在您的标题中只有类定义,而不是其成员函数的定义
- 所以我建立一个DLL项目。但它失败产生的dll,因为缺少
do_something()
函数。正常,因为你的架构它应该在应用程序中不是在DLL中定义!我可以通过使do_something()
virtual解决问题。 - 然后我构建应用程序。我首先选择为简单和链接的应用程序与DLL(没有加载问题)。不幸的是,它没有找到
MemberFunc()
也不是createInstance()
。我可以通过导出DLL条目解决这个问题。 - FInally我更新了应用程序,动态加载库。为了避免不必要的麻烦找到回来
MemberFunc()
,我做了虚拟,以及。
在上述所有测试中,我完全没有问题。 IntArray
始终正确。在调试模式下,我可以看到它与预期的内容,一旦它进入范围。
我的结论是,从这些测试和看你的代码段(特别是doSomething不是虚拟的):你的问题可能 code>在 Main.h
中的 SomeType
类和最终 IntArray
如果是这样,你的DLL指的是它自己的这些元素的副本,而不是你认为主要的那些!这就解释了为什么你看不到预期的值!
解决方案:
文件 MainApp.h :
class SomeType {
public:
SomeType();
virtual void do_something();
};
文件 MyDLL.h :
#ifdef MyDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class A {
public:
A(SomeType * data);
virtual void MemberFunc(); //通过vtable访问。无需链接
private:
SomeType * m_data;
};
externC{//使用动态加载的DLL的简单名称使用无名称
MYDLL_API A * createInstance(SomeType * data);
};
文件 MyDLL.cpp :
#define MYDLL_EXPORTS
#includeMainApp.h
#includeMyDLL.h
A: :A(SomeType * data):m_data {data} {}
void A :: MemberFunc(){m_data-> do_something }
externC{
MYDLL_API A * cdecl createInstance(SomeType * data){return new A(data); }
}
文件 main.cpp :
#include< Windows.h>
#include< iostream>
#include< vector>
#includeMainApp.h
#includeMyDLL.h
using namespace std;
vector< int> IntArray;
SomeType :: SomeType(){
IntArray.resize(1000);
IntArray [0] = 1; IntArray [1] = 101; IntArray [2] = 10101;
}
void SomeType :: do_something(){
for(int i = 0; i <4; i ++)// read
cout< IntArray [i]< endl
IntArray [3] = 2702; // write
}
int main(int ac,char ** av)
{
HINSTANCE LoadMe = LoadLibrary(LMyDLL.dll);
if(LoadMe!= 0)
cout<< DLL库成功加载!\\\
;
else throw exception(DLL库无法加载!\\\
);
typedef A *(* _ createInstance)(SomeType *);
_createInstance fcreateInstance =(_createInstance)GetProcAddress(LoadMe,createInstance);
if(fcreateInstance)
cout<< DLL function found!\\\
;
else throw exception(DLL not found in DLL!\\\
);
SomeType someType;
A * a = fcreateInstance(& someType);
a-> MemberFunc();
cin.get();
}
I have a dll plugin ,myDLL.cpp, which has the following code:
#include "myDLL.h"
#include "MainApp.h"
class A{
public:
// NOTE: SomeType is defined in main application code.
A(SomeType* data) : m_data{data}
void MemberFunc(){
// NOTE: do_something should access data in main application.
m_data->do_something();
}
private:
SomeType* m_data;
};
// exported function
A* createInstance(SomeType* data){
return new A(data);
}
In the main application I have:
stc::vector<int> IntArray;
class SomeType{
SomeType(){
IntArray.resize(1000);
}
void do_something(){
// manipulate IntArray's contents.
IntArray[rand() % IntArray.size()] = rand();
}
};
typedef A*(_createInstance)(SomeType*);
void main(){
// Load the Dll and get createInstance()
_createInstance createInstance = LoadMyDLL();
SomeType someType;
A* a = createInstance(&someType);
a->MemberFunc();
// Free the instance of A and unload the DLL.
UnloadMyDLL(a);
}
The dll code now can use the API of the main application, but it can't access the right data. When I put a break point at m_data->do_something();
and enter the method call, then I see that IntArray
is empty. What am I doing wrong and how do I solve the problem?
I could succesfully run your example without experiencing your problem:
- I assumed that in your headers there are only the class definitions and not definition of its member functions
- So I buid a DLL project. But it failed producing the dll because of the missing
do_something()
function. Normal, because with your architecture it should be defined in the application not in the DLL ! I could solve the problem by makingdo_something()
virtual. - Then I build the application. I first chose for simplicity and linked the application with the DLL (no loading issues). Unfortunately it didn't find either
MemberFunc()
norcreateInstance()
. I could solve this by exporting the DLL entry. - FInally I updated the application, to have a dynamic load of the library. For avoiding unnecessary hassle of having to find back
MemberFunc()
, I made it virtual as well.
In all the tests above, I had absolutely no problem. IntArray
was always correct. In debug mode I could see it with the expected content, as soon as it entered the scope.
My conclusion, from these tests and looking at your snippet (expecially with doSomething not being virtual): your problem is probably that have defined SomeType
class with functions and eventually IntArray
in Main.h
.
If this is the case, your DLL refers to its own copy of these elements and not as you think to those in main ! THis explains why you don't see the expected values !
Solution:
File MainApp.h:
class SomeType{
public:
SomeType();
virtual void do_something();
};
File MyDLL.h:
#ifdef MYDLL_EXPORTS
#define MYDLL_API __declspec(dllexport)
#else
#define MYDLL_API __declspec(dllimport)
#endif
class A {
public:
A(SomeType* data);
virtual void MemberFunc(); // access through vtable. No need to link
private:
SomeType* m_data;
};
extern "C" { // use unmangled name for easo of use of dynamic loaded DLL
MYDLL_API A* createInstance(SomeType* data);
};
File MyDLL.cpp:
#define MYDLL_EXPORTS
#include "MainApp.h"
#include "MyDLL.h"
A::A(SomeType* data) : m_data{ data } {}
void A::MemberFunc(){ m_data->do_something(); }
extern "C" {
MYDLL_API A* cdecl createInstance(SomeType* data){ return new A(data); }
}
File main.cpp:
#include <Windows.h>
#include <iostream>
#include <vector>
#include "MainApp.h"
#include "MyDLL.h"
using namespace std;
vector<int> IntArray;
SomeType::SomeType(){
IntArray.resize(1000);
IntArray[0] = 1; IntArray[1] = 101; IntArray[2] = 10101;
}
void SomeType::do_something(){
for (int i = 0; i < 4; i++) // read
cout << IntArray[i] << endl;
IntArray[3] = 2702; // write
}
int main(int ac, char**av)
{
HINSTANCE LoadMe = LoadLibrary(L"MyDLL.dll");
if(LoadMe != 0)
cout << "DLL Library successfully loaded!\n";
else throw exception("DLL library failed to load!\n");
typedef A*(*_createInstance)(SomeType*);
_createInstance fcreateInstance = (_createInstance) GetProcAddress(LoadMe, "createInstance");
if (fcreateInstance)
cout << "DLL function found !\n";
else throw exception("Function not found in DLL!\n");
SomeType someType;
A* a = fcreateInstance(&someType);
a->MemberFunc();
cin.get();
}
这篇关于将应用程序API和数据暴露给DLL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!