Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/138.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 向DLL公开应用程序API和数据_C++_Dll_Plugins - Fatal编程技术网

C++ 向DLL公开应用程序API和数据

C++ 向DLL公开应用程序API和数据,c++,dll,plugins,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

我有一个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);
}
stc::向量数组;
类SomeType{
SomeType(){
调整数组大小(1000);
}
空做某事{
//操纵IntArray的内容。
IntArray[rand()%IntArray.size()]=rand();
}
};
typedef A*(_createInstance)(SomeType*);
void main(){
//加载Dll并获取createInstance()
_createInstance createInstance=LoadMyDLL();
某种类型某种类型;
A*A=createInstance(&someType);
a->MemberFunc();
//释放实例并卸载DLL。
Unloadmydell(a);
}

dll代码现在可以使用主应用程序的API,但无法访问正确的数据。当我在
m_data->do_something()处设置断点时
并输入方法调用,然后我看到
IntArray
为空。我做错了什么?如何解决问题?

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

  • 我假设在您的头中只有类定义,而没有其成员函数的定义
  • 所以我建立了一个DLL项目。但是由于缺少
    do\u something()
    函数,它无法生成dll。正常,因为对于您的体系结构,它应该在应用程序中定义,而不是在DLL中!我可以通过使
    do\u something()
    虚拟化来解决这个问题
  • 然后我构建应用程序。为了简单起见,我首先选择将应用程序与DLL链接(没有加载问题)。不幸的是,它既没有找到
    MemberFunc()
    也没有找到
    createInstance()
    。我可以通过导出DLL条目来解决这个问题
  • 最后我更新了应用程序,以动态加载库。为了避免查找
    MemberFunc()
    
在以上所有的测试中,我完全没有问题<代码>阵列始终正确。在调试模式下,我可以看到它与预期的内容,只要它进入范围

我的结论是,通过这些测试并查看您的代码片段(尤其是doSomething不是虚拟的):您的问题可能是定义了
SomeType
类和函数,并最终在
Main.h
中定义了
IntArray

如果是这种情况,您的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);
};  
#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); }
}
#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(); 
}
文件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);
};  
#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); }
}
#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(); 
}
文件main.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);
};  
#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); }
}
#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(); 
}
#包括
#包括
#包括
#包括“MainApp.h”
#包括“MyDLL.h”
使用名称空间std;
矢量阵列;
SomeType::SomeType(){
调整数组大小(1000);
IntArray[0]=1;IntArray[1]=101;IntArray[2]=10101;
}
void SomeType::do_something(){
for(int i=0;i<4;i++)//读取

我可以试一下你的代码吗,一边用dll,另一边用应用程序制作一个VS解决方案。我在应用程序中定义了对dll的引用,所以我不必使用你的
LoadMyDLL()
。它工作得很好。唯一的问题是InArray在断点上不可见:只有当我用F11进入doSomething()时我可以检查一下吗。