将应用程序API和数据暴露给DLL [英] Exposing application API and data to DLL

查看:209
本文介绍了将应用程序API和数据暴露给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 making do_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() nor createInstance(). 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆