How to use a class in DLL?
Solution 1
If you use run time dynamic linking (uses LoadLibrary to load the dll) you cannot access the class directly, you need to declare a interface for your class and create a function that returns a instance of this class, like this:
class ISDLConsole
{
public:
virtual void getInfo(int,int) = 0;
virtual void initConsole(char*, char*, SDL_Surface*, int, int, int) = 0;
virtual void sendMsg(char*,int, SDL_Surface*) = 0;
virtual void cls(SDL_Surface*) = 0;
};
class SDLConsole: public ISDLConsole
{
//rest of the code
};
__declspec(dllexport) ISDLConsole *Create()
{
return new SDLConsole();
}
Otherwise, if you link the dll during load time, just use the information provided by icecrime: http://msdn.microsoft.com/en-us/library/a90k134d.aspx
Solution 2
Solution suggested by bcsanches,
__declspec(dllexport) ISDLConsole *Create()
{
return new SDLConsole();
}
If you're going to use this approach as suggested by bcsanches, then make sure that you use the following function to delete
your object,
__declspec(dllexport) void Destroy(ISDLConsole *instance)
{
delete instance;
}
Define such functions always in pair, as it ensures that you delete your objects from the same heap/memory-pool/etc they were created on. See this pair-functions
Solution 3
You can, and all the information you need are on this page and this page :
#ifdef _EXPORTING
#define CLASS_DECLSPEC __declspec(dllexport)
#else
#define CLASS_DECLSPEC __declspec(dllimport)
#endif
class CLASS_DECLSPEC SDLConsole
{
/* ... */
};
All there is left is to define the preprocessor symbol _EXPORTING
when building the DLL.
Solution 4
If you want to expose the data in a class, the above solutions won't cut it. You have to slap a __declspec(dllexport)
on the class itself in the DLL compilation, and a __declspec(dllimport)
in the module that links to the DLL.
A common technique is to do this (Microsoft wizards produce code like this):
#ifdef EXPORT_API
#define MY_API __declspec(dllexport)
#else
#define MY_API __declspec(dllimport)
#endif
class MY_API MyClass {
...
};
Then make sure EXPORT_API
is defined in the DLL project, and make sure it isn't defined in the module that links to the DLL.
If you create a new DLL project in Visual C++ from scratch, and check the check box "Export symbols", some sample code will be generated using this technique.
r1cebank
Updated on September 26, 2020Comments
-
r1cebank over 3 years
Can I put a class inside a DLL? The class i wrote is this:
class SDLConsole { public: SDLConsole(); ~SDLConsole(){}; void getInfo(int,int); void initConsole(char*, char*, SDL_Surface*, int, int, int); void sendMsg(char*,int, SDL_Surface*); void cls(SDL_Surface*); private: TTF_Font *font; SDL_Surface *consoleImg; int width, pos, height, line, size, ctLine; SDL_Surface* render(char*,int); };
I know how to load a DLL and use the function inside a DLL, but how can I put a class inside a DLL? Thank you very much.
-
Ben Voigt over 13 yearsThis way is much more robust than
__declspec(dllexport)
. Even load-time linking should use this method. -
Ben Voigt over 13 yearsThat's not "all there is left". You also need to make sure that the same exact compiler is used for building the DLL and all clients, that compiler options also match. You pay a huge maintainability penalty for doing things this way, the pure virtual interface as suggested by bcsanches is much better.
-
icecrime over 13 years@Ben: you're probably right, but I have to admit I've always done things this way and that I just cannot imagine using the 'pure virtual interface' method on a big project
-
Ben Voigt over 13 yearsBecause only the v-table layout has to match between library and client, which is relatively easy to accomplish, even between different languages. On the other hand, with
__declspec(dllexport)
everything has to match: compiler vendor, compiler version, compile options, or you will either end up with name-mangling mismatch (link error) or a one-definition-rule violation and corresponding crashes. -
Ben Voigt over 13 yearsEventually you end with a situation where you have to compile your application with version X of the compiler, since that's what library A uses. Then you want to use library B, but you can't, because it requires version Y of the compiler.
-
Ben Voigt over 13 yearsIf you've got modules which are closely coupled because they're all local to a single project, why not just use static libraries?
-
Rob over 13 yearsIn all my years as a Windows C++ developer I have never come across this trick before - excellent answer and something I will definitely be using myself.
-
Hossein almost 11 yearsI want to create a dll out of my c++ class and use that dll in my C# application. can you please guide me on that too? what else is needed? how can i call my dll in c# when i create it this way?
-
Nawaz almost 11 years@Hossein: Search for pinvoke in C#. You will find lots of topics on it.
-
Hossein almost 11 yearsyou mean i need to use the conventional DIIIMport just like normal dlls (such as user32.dll)? ok i'll give it a try
-
Hossein almost 11 yearsOk here is the problem! How should i specify the return type of my factory class? public static extern object?! Create_xGramManilpulator(wchar_t* filename); and what should i use in C# to address vector<string> and wchar_t* type?
-
spt025 almost 9 yearsHow do we call class method in our process from dll if we use this method.
-
bcsanches almost 9 years@spt025 your dll will be loaded by the process and it needs a entry point so the process can "init" or call something there. When it does that, it can provide a pointer to the class or a function pointer that your dll can call to instantiate the class.
-
Zach almost 9 years@bcsanches, can I use std::shared_ptr<ISDLConsole> when return an instance?
-
bcsanches almost 9 years@Zach I do not see any problem. You may be aware that shared_ptr and friends are template code, implemented on header, so who includes your header file, must have the exactly same version of the lib that you have, otherwise they may have trouble. I have done this lot of times and never had a issue.
-
stakx - no longer contributing almost 8 yearsPerhaps the COM (Component Object Model) deserves mention in this answer, because it works in pretty much the same way: The entry point function is called
DllGetClassObject
, and you only ever receive interface pointers. -
stakx - no longer contributing almost 8 years@Nawaz: If you want to export a C++ class to C#, you need to do two things: lay out your class like a COM class (i.e. have it implement
IUnknown
and follow the COM protocol) so that you can use COM interop on the .NET side. Second, export a factory function from your DLL that returns an instance of your class, as suggested in bcsanches' answer, which you then[DllImport]
from your .NET code. -
truthadjustr almost 6 yearsThe subtle thing to note here is that, you can actually access the class if you use an import library and thus will result to a static linking. The import library .lib is paired with it's corresponding .dll but you do not use LoadLibrary/GetProcAddress to load this dll. On the other hand, if you use LoadLibrary/GetProcAddress technique then you have no visibility of the class definition and is thus forced to rely on a base class or via COM (IUnknown, IDispatch) technique, either which it is requiring a common base class that could poke into the object that is hidden in the DLL.