将应用程序API和数据公开给DLL

时间:2015-02-21 17:05:48

标签: c++ dll plugins

我有一个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为空。我做错了什么,如何解决问题?

1 个答案:

答案 0 :(得分:1)

我可以成功运行您的示例而不会遇到您的问题:

  • 我假设在你的标题中只有类定义而不是其成员函数的定义
  • 所以我建了一个DLL项目。但由于缺少do_something()函数,它无法生成dll。正常,因为你的架构应该在应用程序中定义而不是在DLL中!我可以通过使do_something()虚拟来解决问题。
  • 然后我构建应用程序。我首先选择简单并将应用程序与DLL链接(没有加载问题)。很遗憾,它找不到MemberFunc()createInstance()。我可以通过导出DLL条目来解决这个问题。
  • 最后,我更新了应用程序,以动态加载库。为了避免不必要找回MemberFunc()的麻烦,我也将其设为虚拟。

在上面的所有测试中,我完全没有问题。 IntArray始终是正确的。在调试模式下,只要它进入范围,我就能看到预期的内容。

我的结论,从这些测试中看到你的片段(特别是doSomething不是虚拟的):你的问题可能是,它定义了带有函数的SomeType类,最终{{1在IntArray中。

如果是这种情况,你的DLL会引用它自己的这些元素的副本,而不是你想到的那些元素!这解释了为什么你没有看到预期值!

解决方案:

文件 MainApp.h

Main.h

档案 MyDLL.h

class SomeType{
public:
    SomeType();
    virtual void do_something();
};

档案 MyDLL.cpp

#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);
};  

档案 main.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); }
}