9

How to create some class from dll(constructor in dll)?(C++) or how to dynamically load class from dll?

Cœur
  • 37,241
  • 25
  • 195
  • 267
SomeUser
  • 1,976
  • 15
  • 42
  • 60

4 Answers4

10

You need to declare your class using the __declspec(dllexport) keyword when building the DLL. When using the DLL, the class needs to be declared with __declspec(dllimport):

#ifdef COMPILING_DLL
#define DECLSPEC_CLASS __declspec(dllexport)
#else
#define DECLSPEC_CLASS __declspec(dllimport)
#endif

class DECLSPEC_CLASS MyClass
{
...
}

When the DLL is compiled, you should add -DCOMPILING_DLL to the list of defines.

When using the class, you must statically link with the DLL, i.e. pass the import library mydll.lib to the main program.

If you want to load the DLL at runtime, you need to have a C-function in the DLL which creates a object and returns it for you. There is no way to lookup a constructor dynamically in a DLL (using GetProcAddress()).

JesperE
  • 63,317
  • 21
  • 138
  • 197
3

You will need to export a function from the DLL that calls on to the constructor and returns the new object.

Try to avoid using concrete C++ types as function parameters; the idea of DLLs is that you can independently update them, but an upgraded compiler may lay out std::string differently, causing incompatibility at runtime.

This is what is at the root of COM, for example - a limited type system and a standard exported function for getting instances of objects.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
  • Tt sounds as if the DLL's source is not under his control. – Frank Bollack Oct 04 '09 at 14:08
  • DLL source is under my control – SomeUser Oct 04 '09 at 14:11
  • If the class is intended to be used, then it should probably already be compiled with __declspec(dllexport), so then it is only a matter of convincing the header file to put __declspec(dllimport) in the class definition. If not, you can always modify the header file yourself. – JesperE Oct 04 '09 at 14:12
3

Answering your question strictly, you need to add an extern "C" function that returns the result of the constructor:

extern "C" foo* __declspec(dllexport) new_foo(int x) {
    return new foo(x);
}

Then in your source you can use GetProcAddr on "new_foo" to call the function.

jmucchiello
  • 18,754
  • 7
  • 41
  • 61
3

Instead of exporting every method of the class using __declspec, you can also rely on the fact that the compiler can invoke virtual functions via the vtable, so for example:

//note: no __declspec
class IPublicInterface
{
  virtual ~IPublicInterface() = 0;
  virtual void SomeMethod() = 0;
};

//note: no __declspec
class SomeClass : IPublicInterface
{
  virtual ~SomeClass() { ... }
  virtual void SomeMethod() { ... }
};

//note: this is the only method which needs to be exported from the DLL
IPublicInterface* createSomeClass()
{
  return new SomeClass();
}
ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • interface/factory pattern is nice, especially if you're going to use `GetProcAddress` and manually managed .def exports table – Janusz Lenar Nov 14 '10 at 21:08
  • Since memory is allocated in the DLL, maybe there should also be a `freeSomClass(IPublicInterface*)` just to make sure memory is freed correctly ? – Robert Nov 28 '13 at 10:40
  • I think this answer is wrong and should be deleted. You can't pass a polymorphic object across a plugin boundary, except when the exact same compiler is used in both the plugin and the application. – Julien__ Feb 13 '15 at 18:10