Encapsulating static libraries in dynamic-link libraries (DLL) - c++

I'm trying to increase my understanding of basic library linking, dependencies, etc. I created a Visual Studio solution with three projects
Static lib using /MTd with a single class (Foo), one method int GetNum() { return 5; }
Shared dll using /MDd with a single class (Bar), one method int GetNum() { Foo f; return f.GetNum(); }
Win32 console app. That calls Bar b; std::cout << b.GetNum() << std::endl
When I tried to build this, it complained it couldn't find my dll's associated lib. Did a little research, saw that I needed to add __declspec(dllexport) to my GetNum() method and I'd get a .lib. Cool.
Next hurtle was the console app said it couldn't find the static lib for Foo. I added it to my references and it all build and ran fine.
My question is - why does my exe need to know anything about Foo? I wanted to effectively "bake" in all my dependencies into the dll so I could just share that, link into it, and be good to go.
Is this just not how the language works or a setting / pattern I'm missing? My end goal is to be able to build a dll that encapsulates the usage of third party .lib's and not have the client app need to worry about adding references to all of them.
Update
Here is most of the code.
// ---------------------- Lib (e.g. Foo)
#pragma once
class MathLib
{
public:
MathLib(void);
~MathLib(void);
int GetNum() { return 83; }
};
// ---------------------- DLL (e.g. Bar)
#pragma once
#ifdef CONSOLETEST_EXPORT
#define CONSOLETEST_API __declspec(dllexport)
#else
#define CONSOLETEST_API __declspec(dllimport)
#endif
#include "MathLib.h"
class MathDll
{
public:
__declspec(dllexport) MathDll(void);
__declspec(dllexport) ~MathDll(void);
__declspec(dllexport) int GetNumFromDyn()
{
MathLib m;
return m.GetNum();
}
};
// ---------------------- exe
int _tmain(int argc, _TCHAR* argv[])
{
MathDll m;
std::cout << "num is " << m.GetNumFromDyn() << std::endl;
return 0;
}

With C/C++, it's very important to structure your code properly across headers (e.g. h, hpp, hxx, h++, etc.) and translation units (usually called sources, e.g. c, cpp, cxx, c++, etc.). When you design a library, you should be constantly thinking what belongs to its interface (i.e. supposed to be seen by consumers) and what belongs to its implementation (i.e. not supposed to be seen by consumers).
Remember the rule of thumb - all symbols that are present in any header will be seen by consumers (if included), and, as a result, required by consumers to be resolved during linking stage at some point in time later!
This is essentially what happened to you in your toy example. So let's fix it by using a simple rule, which you should remember by heart: Put as much as possible into translation units, i.e. keep headers minimal. Now let's use your example to show how it works:
MathLib.hpp:
#pragma once
class MathLib {
public:
MathLib();
~MathLib();
int GetNum();
};
MathLib.cpp:
#include "MathLib.hpp"
MathLib::MathLib() {}
MathLib::~MathLib() {}
int MathLib::GetNum() { return 83; }
Now build MathLib.cpp as static library.
MathDll.hpp:
#pragma once
#ifdef CONSOLETEST_EXPORT
# define CONSOLETEST_API __declspec(dllexport)
#else
# define CONSOLETEST_API __declspec(dllimport)
#endif
class CONSOLETEST_API MathDll {
public:
MathDll();
~MathDll();
int GetNumFromDyn();
};
MathDll.cpp:
#include "MathDll.hpp"
#include "MathLib.hpp"
MathDll::MathDll() {}
MathDll::~MathDll() {}
int MathDll::GetNumFromDyn() {
MathLib m;
return m.GetNum();
}
Now build MathDll.cpp as dynamic-link library (DLL) and don't forget to add definition CONSOLETEST_EXPORT during its build, so that CONSOLETEST_API is __declspec(dllexport), and, as a result, an import library with exported symbols (i.e. the MathDll class and its methods) is generated for the DLL. On MSVC you can achieve this by adding /DCONSOLETEST_API to the invocation of compiler. Finally, when building this DLL, certainly link it with previously built static library, MathLib.lib.
NOTE: It's better to export the whole class like I did above with class CONSOLETEST_API MathDll, rather than export all methods individually.
main.cpp:
#include "MathDll.hpp"
#include <iostream>
int _tmain(int argc, _TCHAR* argv[]) {
MathDll m;
std::cout << "num is " << m.GetNumFromDyn() << std::endl;
return 0;
}
Now build main.cpp as console application and only link it with previously built import library for DLL, MathDll.lib.
Notice how the problem is gone because I've got rid of transitive dependency to MathLib (through MathDll.hpp) from main.cpp, since now the #include "MathLib.hpp" inclusion is done in the translation unit MathDll.cpp (because it's actually only needed there according to above rule), and is therefore built into binary artifact (DLL in this case) and not present in its interface.
Understanding all of this is really important for proper native software development with C/C++, so it's really good that you ask this question beforehand. I meet people who don't know/understand this quite often, what results in complete nightmare for them (amateurs), and us, when we have to deal with that crappy software they write...

Consider the case when MathLib is a part of MathDll class.
//MathDll.h
#include "MathLib.h"
class MathDll
{
private:
MathLib m;
public:
__declspec(dllexport) MathDll(void);
__declspec(dllexport) ~MathDll(void);
__declspec(dllexport) int GetNumFromDyn()
{
return m.GetNum();
}
};
you will have to now include MathLib.h into your MathDll.h, which propagates to the console app too.
You can avoid this...
By using PIMPL idiom to encapsulate everything into the DLL.
Provide the forward declaration of the class MathLib in the header and the rest of the implemenation hidden in the Dll. You can also consider exporting the whole class.
//------------MathDll.h
// we do not include "MathLib.h" here. include it in the MathDll.cpp only
class MathLib;
class __declspec(dllexport) MathDll
{
private:
MathLib* m;
public:
MathDll(void);
~MathDll(void);
int GetNumFromDyn();
};
//--------------MathDll.cpp
#include "MathLib.h"
#include "MathDll.h"
MathDll::MathDll(void)
{
m = new MathLib();
}
MathDll::~MathDll(void)
{
delete m;
}
int MathDll::GetNumFromDyn()
{
return m->GetNum();
}

Related

dll: how to make a dll with some cpp classes [duplicate]

Most of my C/C++ development involves monolithic module files and absolutely no classes whatsoever, so usually when I need to make a DLL with accessible functions I just export them using the standard __declspec(dllexport) directive. Then access them either dynamically via LoadLibrary() or at compile time with a header and lib file.
How do you do this when you want to export an entire class (and all it's public methods and properties)?
Is it possible to dynamically load that class at runtime and if so, how?
How would you do it with a header and lib for compile time linking?
What about late-binding? As in loading
it with LoadLibrary() and
GetProcAddress() ? I'm used being able
to load the library at run time and it
would be great if you could do that
here.
So there are two ways to load the DLL. The first is to reference one or more symbols from the DLL (your classname, for example), supply an appropriate import .LIB and let the linker figure everything out.
The second is to explicitly load the DLL via LoadLibrary.
Either approach works fine for C-level function exports. You can either let the linker handle it or call GetProcAddress as you noted.
But when it comes to exported classes, typically only the first approach is used, i.e., implicitly link to the DLL. In this case the DLL is loaded at application start time, and the application fails to load if the DLL can't be found.
If you want to link to a class defined in a DLL, and you want that DLL to be loaded dynamically, sometime after program initiation, you have two options:
Create objects of the class using a special factory function, which internally will have to use (a tiny bit of) assembler to "hook up" newly created objects to their appropriate offsets. This has to be done at run-time AFTER the DLL has been loaded, obviously. A good explanation of this approach can be found here.
Use a delay-load DLL.
All things considered... probably better to just go with implicit linking, in which case you definitely want to use the preprocessor technique shown above. In fact, if you create a new DLL in Visual Studio and choose the "export symbols" option these macros will be created for you.
Good luck...
When you build the DLL and the module that will use the DLL, have some kind of #define that you can use to distinguish between one and the other, then you can do something like this in your class header file:
#if defined( BUILD_DLL )
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif
class IMPORT_EXPORT MyClass {
...
};
Edit: crashmstr beat me to it!
Adding a simple working example for exporting a C++ class from a DLL :
The given below example gives you only a short overview of how dll and exe can interact each other (self explanatory ) but it needs more things to add for changing into a production code.
Full sample example is divided in to two part
A. Creating a .dll library (MyDLL.dll)
B. Creating an Application which uses .dll library (Application).
A. .dll project file (MyDLL.dll):
1. dllHeader.h
#ifdef MYDLL_EXPORTS
#define DLLCALL __declspec(dllexport) /* Should be enabled before compiling
.dll project for creating .dll*/
#else
#define DLLCALL __declspec(dllimport) /* Should be enabled in Application side
for using already created .dll*/
#endif
// Interface Class
class ImyMath {
public:
virtual ~ImyMath() {;}
virtual int Add(int a, int b) = 0;
virtual int Subtract(int a, int b) = 0;
};
// Concrete Class
class MyMath: public ImyMath {
public:
MyMath() {}
int Add(int a, int b);
int Subtract(int a, int b);
int a,b;
};
// Factory function that will return the new object instance. (Only function
// should be declared with DLLCALL)
extern "C" /*Important for avoiding Name decoration*/
{
DLLCALL ImyMath* _cdecl CreateMathObject();
};
// Function Pointer Declaration of CreateMathObject() [Entry Point Function]
typedef ImyMath* (*CREATE_MATH) ();
2. dllSrc.cpp
#include "dllHeader.h"
// Create Object
DLLCALL ImyMath* _cdecl CreateMathObject() {
return new MyMath();
}
int MyMath::Add(int a, int b) {
return a+b;
}
int MyMath::Subtract(int a, int b) {
return a-b;
}
B. Application Project which load and link the already created .dll file:
#include <iostream>
#include <windows.h>
#include "dllHeader.h"
int main()
{
HINSTANCE hDLL = LoadLibrary(L"MyDLL.dll"); // L".\Debug\MyDLL.dll"
if (hDLL == NULL) {
std::cout << "Failed to load library.\n";
}
else {
CREATE_MATH pEntryFunction = (CREATE_MATH)GetProcAddress(hDLL,"CreateMathObject");
ImyMath* pMath = pEntryFunction();
if (pMath) {
std::cout << "10+10=" << pMath->Add(10, 10) << std::endl;
std::cout << "50-10=" << pMath->Subtract(50, 10) << std::endl;
}
FreeLibrary(hDLL);
}
std::cin.get();
return 0;
}
I use some macros to mark the code for import or export
#ifdef ISDLL
#define DLL __declspec(dllexport)
#endif
#ifdef USEDLL
#define DLL __declspec(dllimport)
#endif
Then declare the class in a header file:
class DLL MyClassToExport { ... }
Then #define ISDLL in the libary, and USEDLL before including the header file in the place you want to use the class.
I don't know if you might need to do anything differently for working with LoadLibrary
Recently I asked myself exactly the same question, and summarized my findings in a blog post. You may find it useful.
It covers exporting C++ classes from a DLL, as well as loading them dynamically with LoadLibrary, and discusses some of the issues around that, such as memory management, name mangling and calling conventions.
If you're willing to put a vtable in the class you're exporting, you can export a function that returns an interface and implement the class in the .dll, then put that in the .def file. You might have to do some declaration trickery, but it shouldn't be too hard.
Just like COM. :)

how to transform my c++ for exe to a code for dll [duplicate]

Most of my C/C++ development involves monolithic module files and absolutely no classes whatsoever, so usually when I need to make a DLL with accessible functions I just export them using the standard __declspec(dllexport) directive. Then access them either dynamically via LoadLibrary() or at compile time with a header and lib file.
How do you do this when you want to export an entire class (and all it's public methods and properties)?
Is it possible to dynamically load that class at runtime and if so, how?
How would you do it with a header and lib for compile time linking?
What about late-binding? As in loading
it with LoadLibrary() and
GetProcAddress() ? I'm used being able
to load the library at run time and it
would be great if you could do that
here.
So there are two ways to load the DLL. The first is to reference one or more symbols from the DLL (your classname, for example), supply an appropriate import .LIB and let the linker figure everything out.
The second is to explicitly load the DLL via LoadLibrary.
Either approach works fine for C-level function exports. You can either let the linker handle it or call GetProcAddress as you noted.
But when it comes to exported classes, typically only the first approach is used, i.e., implicitly link to the DLL. In this case the DLL is loaded at application start time, and the application fails to load if the DLL can't be found.
If you want to link to a class defined in a DLL, and you want that DLL to be loaded dynamically, sometime after program initiation, you have two options:
Create objects of the class using a special factory function, which internally will have to use (a tiny bit of) assembler to "hook up" newly created objects to their appropriate offsets. This has to be done at run-time AFTER the DLL has been loaded, obviously. A good explanation of this approach can be found here.
Use a delay-load DLL.
All things considered... probably better to just go with implicit linking, in which case you definitely want to use the preprocessor technique shown above. In fact, if you create a new DLL in Visual Studio and choose the "export symbols" option these macros will be created for you.
Good luck...
When you build the DLL and the module that will use the DLL, have some kind of #define that you can use to distinguish between one and the other, then you can do something like this in your class header file:
#if defined( BUILD_DLL )
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif
class IMPORT_EXPORT MyClass {
...
};
Edit: crashmstr beat me to it!
Adding a simple working example for exporting a C++ class from a DLL :
The given below example gives you only a short overview of how dll and exe can interact each other (self explanatory ) but it needs more things to add for changing into a production code.
Full sample example is divided in to two part
A. Creating a .dll library (MyDLL.dll)
B. Creating an Application which uses .dll library (Application).
A. .dll project file (MyDLL.dll):
1. dllHeader.h
#ifdef MYDLL_EXPORTS
#define DLLCALL __declspec(dllexport) /* Should be enabled before compiling
.dll project for creating .dll*/
#else
#define DLLCALL __declspec(dllimport) /* Should be enabled in Application side
for using already created .dll*/
#endif
// Interface Class
class ImyMath {
public:
virtual ~ImyMath() {;}
virtual int Add(int a, int b) = 0;
virtual int Subtract(int a, int b) = 0;
};
// Concrete Class
class MyMath: public ImyMath {
public:
MyMath() {}
int Add(int a, int b);
int Subtract(int a, int b);
int a,b;
};
// Factory function that will return the new object instance. (Only function
// should be declared with DLLCALL)
extern "C" /*Important for avoiding Name decoration*/
{
DLLCALL ImyMath* _cdecl CreateMathObject();
};
// Function Pointer Declaration of CreateMathObject() [Entry Point Function]
typedef ImyMath* (*CREATE_MATH) ();
2. dllSrc.cpp
#include "dllHeader.h"
// Create Object
DLLCALL ImyMath* _cdecl CreateMathObject() {
return new MyMath();
}
int MyMath::Add(int a, int b) {
return a+b;
}
int MyMath::Subtract(int a, int b) {
return a-b;
}
B. Application Project which load and link the already created .dll file:
#include <iostream>
#include <windows.h>
#include "dllHeader.h"
int main()
{
HINSTANCE hDLL = LoadLibrary(L"MyDLL.dll"); // L".\Debug\MyDLL.dll"
if (hDLL == NULL) {
std::cout << "Failed to load library.\n";
}
else {
CREATE_MATH pEntryFunction = (CREATE_MATH)GetProcAddress(hDLL,"CreateMathObject");
ImyMath* pMath = pEntryFunction();
if (pMath) {
std::cout << "10+10=" << pMath->Add(10, 10) << std::endl;
std::cout << "50-10=" << pMath->Subtract(50, 10) << std::endl;
}
FreeLibrary(hDLL);
}
std::cin.get();
return 0;
}
I use some macros to mark the code for import or export
#ifdef ISDLL
#define DLL __declspec(dllexport)
#endif
#ifdef USEDLL
#define DLL __declspec(dllimport)
#endif
Then declare the class in a header file:
class DLL MyClassToExport { ... }
Then #define ISDLL in the libary, and USEDLL before including the header file in the place you want to use the class.
I don't know if you might need to do anything differently for working with LoadLibrary
Recently I asked myself exactly the same question, and summarized my findings in a blog post. You may find it useful.
It covers exporting C++ classes from a DLL, as well as loading them dynamically with LoadLibrary, and discusses some of the issues around that, such as memory management, name mangling and calling conventions.
If you're willing to put a vtable in the class you're exporting, you can export a function that returns an interface and implement the class in the .dll, then put that in the .def file. You might have to do some declaration trickery, but it shouldn't be too hard.
Just like COM. :)

C++ DLL calling a function implemented in the consuming application

How to call a post-implemented function (e.g., function pointers or virtual functions implemented in the consuming application) with a complex return type from a DLL function?
I tried the following scheme but got errors.
Test.h:
#ifdef _DLL_IMPL
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
typedef string (*test)(void);
extern DLL_EXPORT test __test;
DLL_EXPORT int launch();
Test.cpp:
#define _DLL_IMPL
#include "Test.h"
test __test = 0;
int launch()
{
string a = __test();
return 0;
}
And the consuming application goes like:
Main.cpp:
#include "Test.h"
#pragma comment(lib, "Test.lib")
string test_impl()
{
string a = "test";
return a;
}
int main(int args, char** argv)
{
__test = &test_impl;
return launch();
}
And I got a subsequent error message:
Windows has triggered a breakpoint in TestRun.exe.
This may be due to a corruption of the heap, which indicates a bug in
TestRun.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while TestRun.exe has focus.
The output window may have more diagnostic information.
I don't know what exactly was going on. Error also occurred when I tried a return type of a char pointer, which would be created in the consuming application using a new operator and would be freed in a DLL function using a delete[] operator.
Can someone explain the reason why the error happens and suggest me some solution to this scheme? Thank you!
Passing C++ objects between exe and dll is really not a good idea, more so if the object is based on a template class and/or has inlined methods, and even more so if the object allocates memory internally. If you need that kind of interface between your application and the library then I recommend that you switch your dll to a static library, then you'll avoid most issues.
If you need to keep the dll as a dll, then I recommend that you only pass native types between exe and dll. In your example, switching all the usages of string to char* will likely address the crashes.
Also take good advice from Jim Rhodes and declare an explicit calling convention, even if you found that that was not the problem in this particular case.
Perhaps you have a calling convention mismatch. Maybe string test_impl() should be string __stdcall test_impl().
You very likely are linking with different versions of the C runtime libraries, preventing shared heap use. Make sure that both the app and dll are linked with the same 'flavor' (dynamic or static) of the C runtime libraries - if you aren't sure which one to pick, set them both to dynamic.
See also Strange problems with new/delete in an app that uses my DLL.
What you really want to export/import is not clear. You export test_impl from main.cpp and import launch in main.cpp from test.cpp
Anyway, you should probably export also classes (std::string).
The following code works perfectly:
//test.cpp
typedef __declspec(dllimport) std::string (*test)(void);
extern __declspec(dllexport) test __test;
test __test = 0;
extern __declspec(dllexport) int launch() { std::string a = __test();
std::cout << a << std::endl ;
return 0; }
// main.cpp
typedef __declspec(dllexport) std::string (*test)(void);
extern __declspec(dllimport) test __test;
extern __declspec(dllimport) test __test;
__declspec(dllimport) int launch();
__declspec(dllexport)
std::string test_impl() {
std::string a = "test";
return a; }
int main(int args, char** argv) {
__test = &test_impl;
return launch(); }
Check however that both projects are compiled with the same model (/MTd, /Mt)

Dynamic link library does not generate a .lib file when compiled (Visual Studio C++ Express)

As part of learning C++, I wrote a simple class library + application that references it. Everything builds, except the class library does not generate a .lib file, which results in the application throwing a "LINK : fatal error LNK1104: cannot open file". This seems very reasonable; obviously, if a necessary file isn't there, there's an error and it's fatal. (Side note: I don't have a book yet)
So, I went looking for reasons a .lib file might not be generated. My search-fu, by the way, is rather weak. All I did find was that, if the library did not have any __declspec(dllexport) tags, it would not export a .lib.
I shall now post the header and .cpp contents of the class library (A simple "Console" class with one "Write(std::string)" method).
Header:
// Extensions.h
#pragma once
#include "stdafx.h"
namespace Extensions {
__declspec(dllexport) class Console
{
public:
__declspec(dllexport) static void Write(std::string text);
};
}
I am unsure whether I need to tag the function when I've tagged the class, but I can check that when it works.
And the .cpp file:
// This is the main DLL file.
#include "stdafx.h"
// #include "Console.h"
namespace Extensions {
void Console::Write(std::string text)
{
std::cout << text.c_str();
}
}
I've checked and it is set to generate a dynamic link library.
Thanks.
Here is some sample code that demonstrates how to correctly export a class. Pay attention to the CONSOLETEST_EXPORT macro. This is the missing part of your solution. You need to define this macro in your DLL project, and leave it undefined in the projects that reference this dll.
// MAIN.CPP - TestApplication
#include <iostream>
#include "ConsoleTest.h"
int main(int argc, char** argv)
{
std::cout << "Hello World" << std::endl;
ConsoleTest test;
test.Write();
ConsoleTest::StaticWrite();
system("pause");
}
// ConsoleTest.h - TestDll
#include <iostream>
#ifdef CONSOLETEST_EXPORT
#define CONSOLETEST_API __declspec(dllexport)
#else
#define CONSOLETEST_API __declspec(dllimport)
#endif
class CONSOLETEST_API ConsoleTest
{
public:
ConsoleTest();
~ConsoleTest();
void Write();
static void StaticWrite();
};
// ConsoleTest.cpp - TestDll
#include "ConsoleTest.h"
ConsoleTest::ConsoleTest()
{
}
ConsoleTest::~ConsoleTest()
{
}
void ConsoleTest::Write()
{
std::cout << "Instance Write" << std::endl;
}
void ConsoleTest::StaticWrite()
{
std::cout << "Static Write" << std::endl;
}
Check out this article on codeproject for more details.
HowTo: Export C++ classes from a DLL

Exporting a C++ class from a DLL

Most of my C/C++ development involves monolithic module files and absolutely no classes whatsoever, so usually when I need to make a DLL with accessible functions I just export them using the standard __declspec(dllexport) directive. Then access them either dynamically via LoadLibrary() or at compile time with a header and lib file.
How do you do this when you want to export an entire class (and all it's public methods and properties)?
Is it possible to dynamically load that class at runtime and if so, how?
How would you do it with a header and lib for compile time linking?
What about late-binding? As in loading
it with LoadLibrary() and
GetProcAddress() ? I'm used being able
to load the library at run time and it
would be great if you could do that
here.
So there are two ways to load the DLL. The first is to reference one or more symbols from the DLL (your classname, for example), supply an appropriate import .LIB and let the linker figure everything out.
The second is to explicitly load the DLL via LoadLibrary.
Either approach works fine for C-level function exports. You can either let the linker handle it or call GetProcAddress as you noted.
But when it comes to exported classes, typically only the first approach is used, i.e., implicitly link to the DLL. In this case the DLL is loaded at application start time, and the application fails to load if the DLL can't be found.
If you want to link to a class defined in a DLL, and you want that DLL to be loaded dynamically, sometime after program initiation, you have two options:
Create objects of the class using a special factory function, which internally will have to use (a tiny bit of) assembler to "hook up" newly created objects to their appropriate offsets. This has to be done at run-time AFTER the DLL has been loaded, obviously. A good explanation of this approach can be found here.
Use a delay-load DLL.
All things considered... probably better to just go with implicit linking, in which case you definitely want to use the preprocessor technique shown above. In fact, if you create a new DLL in Visual Studio and choose the "export symbols" option these macros will be created for you.
Good luck...
When you build the DLL and the module that will use the DLL, have some kind of #define that you can use to distinguish between one and the other, then you can do something like this in your class header file:
#if defined( BUILD_DLL )
#define IMPORT_EXPORT __declspec(dllexport)
#else
#define IMPORT_EXPORT __declspec(dllimport)
#endif
class IMPORT_EXPORT MyClass {
...
};
Edit: crashmstr beat me to it!
Adding a simple working example for exporting a C++ class from a DLL :
The given below example gives you only a short overview of how dll and exe can interact each other (self explanatory ) but it needs more things to add for changing into a production code.
Full sample example is divided in to two part
A. Creating a .dll library (MyDLL.dll)
B. Creating an Application which uses .dll library (Application).
A. .dll project file (MyDLL.dll):
1. dllHeader.h
#ifdef MYDLL_EXPORTS
#define DLLCALL __declspec(dllexport) /* Should be enabled before compiling
.dll project for creating .dll*/
#else
#define DLLCALL __declspec(dllimport) /* Should be enabled in Application side
for using already created .dll*/
#endif
// Interface Class
class ImyMath {
public:
virtual ~ImyMath() {;}
virtual int Add(int a, int b) = 0;
virtual int Subtract(int a, int b) = 0;
};
// Concrete Class
class MyMath: public ImyMath {
public:
MyMath() {}
int Add(int a, int b);
int Subtract(int a, int b);
int a,b;
};
// Factory function that will return the new object instance. (Only function
// should be declared with DLLCALL)
extern "C" /*Important for avoiding Name decoration*/
{
DLLCALL ImyMath* _cdecl CreateMathObject();
};
// Function Pointer Declaration of CreateMathObject() [Entry Point Function]
typedef ImyMath* (*CREATE_MATH) ();
2. dllSrc.cpp
#include "dllHeader.h"
// Create Object
DLLCALL ImyMath* _cdecl CreateMathObject() {
return new MyMath();
}
int MyMath::Add(int a, int b) {
return a+b;
}
int MyMath::Subtract(int a, int b) {
return a-b;
}
B. Application Project which load and link the already created .dll file:
#include <iostream>
#include <windows.h>
#include "dllHeader.h"
int main()
{
HINSTANCE hDLL = LoadLibrary(L"MyDLL.dll"); // L".\Debug\MyDLL.dll"
if (hDLL == NULL) {
std::cout << "Failed to load library.\n";
}
else {
CREATE_MATH pEntryFunction = (CREATE_MATH)GetProcAddress(hDLL,"CreateMathObject");
ImyMath* pMath = pEntryFunction();
if (pMath) {
std::cout << "10+10=" << pMath->Add(10, 10) << std::endl;
std::cout << "50-10=" << pMath->Subtract(50, 10) << std::endl;
}
FreeLibrary(hDLL);
}
std::cin.get();
return 0;
}
I use some macros to mark the code for import or export
#ifdef ISDLL
#define DLL __declspec(dllexport)
#endif
#ifdef USEDLL
#define DLL __declspec(dllimport)
#endif
Then declare the class in a header file:
class DLL MyClassToExport { ... }
Then #define ISDLL in the libary, and USEDLL before including the header file in the place you want to use the class.
I don't know if you might need to do anything differently for working with LoadLibrary
Recently I asked myself exactly the same question, and summarized my findings in a blog post. You may find it useful.
It covers exporting C++ classes from a DLL, as well as loading them dynamically with LoadLibrary, and discusses some of the issues around that, such as memory management, name mangling and calling conventions.
If you're willing to put a vtable in the class you're exporting, you can export a function that returns an interface and implement the class in the .dll, then put that in the .def file. You might have to do some declaration trickery, but it shouldn't be too hard.
Just like COM. :)