1

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?

rashmatash
  • 1,699
  • 13
  • 23
  • I tried your code, making a VS solution with the dll on one side and the app on the other. I defined in my app a reference to the DLL, so I didn't have to use your `LoadMyDLL()`. It worked perfectly. THe only thing was that IntArray was not visible on the breakpoint: only when I steped with F11 into doSomething() could I inspect it. – Christophe Feb 21 '15 at 19:15

1 Answers1

1

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(); 
}
Christophe
  • 68,716
  • 7
  • 72
  • 138