向 DLL 公开应用程序 API 和数据
Exposing application API and data to DLL
我有一个 dll 插件,myDLL.cpp,它有以下代码:
#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);
}
在主应用程序中我有:
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);
}
dll代码现在可以使用主应用程序的API,但是它不能访问正确的数据。当我在 m_data->do_something();
下一个断点并进入方法调用时,我看到 IntArray
是空的。我做错了什么,我该如何解决这个问题?
我可以成功 运行 你的例子而不会遇到你的问题:
- 我假设在你的 headers 中只有 class 定义而不是其成员函数的定义
- 所以我建立了一个DLL项目。但是由于缺少
do_something()
函数,它未能生成 dll。正常,因为对于您的体系结构,它应该在应用程序中而不是在 DLL 中定义!我可以通过将 do_something()
虚拟化来解决问题。
- 然后我构建应用程序。为了简单起见,我首先选择并将应用程序与 DLL 链接(没有加载问题)。不幸的是,它既没有找到
MemberFunc()
也没有找到 createInstance()
。我可以通过导出 DLL 条目来解决这个问题。
- 最后我更新了应用程序,以动态加载库。为了避免不必要的找回
MemberFunc()
的麻烦,我也将其设为虚拟。
在上面的所有测试中,我完全没有问题。 IntArray
总是正确的。在调试模式下,一旦它进入范围,我就可以看到它的预期内容。
我的结论是,根据这些测试并查看您的代码片段(特别是 doSomething 不是虚拟的):您的问题可能 已经定义了 SomeType
class 具有函数,最终 IntArray
在 Main.h
中。
如果是这种情况,您的 DLL 将引用这些元素自己的副本,而不是您认为的 main 中的那些!这解释了为什么您看不到预期值!
解决方案:
文件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(); // 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);
};
文件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); }
}
文件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();
}
我有一个 dll 插件,myDLL.cpp,它有以下代码:
#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);
}
在主应用程序中我有:
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);
}
dll代码现在可以使用主应用程序的API,但是它不能访问正确的数据。当我在 m_data->do_something();
下一个断点并进入方法调用时,我看到 IntArray
是空的。我做错了什么,我该如何解决这个问题?
我可以成功 运行 你的例子而不会遇到你的问题:
- 我假设在你的 headers 中只有 class 定义而不是其成员函数的定义
- 所以我建立了一个DLL项目。但是由于缺少
do_something()
函数,它未能生成 dll。正常,因为对于您的体系结构,它应该在应用程序中而不是在 DLL 中定义!我可以通过将do_something()
虚拟化来解决问题。 - 然后我构建应用程序。为了简单起见,我首先选择并将应用程序与 DLL 链接(没有加载问题)。不幸的是,它既没有找到
MemberFunc()
也没有找到createInstance()
。我可以通过导出 DLL 条目来解决这个问题。 - 最后我更新了应用程序,以动态加载库。为了避免不必要的找回
MemberFunc()
的麻烦,我也将其设为虚拟。
在上面的所有测试中,我完全没有问题。 IntArray
总是正确的。在调试模式下,一旦它进入范围,我就可以看到它的预期内容。
我的结论是,根据这些测试并查看您的代码片段(特别是 doSomething 不是虚拟的):您的问题可能 已经定义了 SomeType
class 具有函数,最终 IntArray
在 Main.h
中。
如果是这种情况,您的 DLL 将引用这些元素自己的副本,而不是您认为的 main 中的那些!这解释了为什么您看不到预期值!
解决方案:
文件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(); // 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);
};
文件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); }
}
文件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();
}