C++: Dynamically loading classes from dlls - c++

For my current project I want to be able to load some classes from a dll (which is not always the same, and may not even exist when my app is compiled). There may also be several alternative dll's for a given class (eg an implementation for Direct3D9 and one for OpenGL), but only one of the dlls will be loaded/used at any one time.
I have a set of base classes that define the interface plus some basic methods/members (ie the ones for refrence counting) of the classes I want to load, which the dll projects then derive from when creating there classes.
//in namespace base
class Sprite : public RefCounted//void AddRef(), void Release() and unsigned refCnt
{
public:
virtual base::Texture *GetTexture()=0;
virtual unsigned GetWidth()=0;
virtual unsigned GetHeight()=0;
virtual float GetCentreX()=0;
virtual float GetCentreY()=0;
virtual void SetCentre(float x, float y)=0;
virtual void Draw(float x, float y)=0;
virtual void Draw(float x, float y, float angle)=0;
virtual void Draw(float x, float y, float scaleX, flota scaleY)=0;
virtual void Draw(float x, float y, float scaleX, flota scaleY, float angle)=0;
};
The thing is I'm not sure how to do it all so that the executable and other dlls can load and use these classes since ive only ever used dlls where there was only one dll and I could have the Visual Studio linker sort it all out using the .lib file I get when compileing dll's.
I dont mind using factory methods for instancing the classes, many of them do already by design (Ie a sprite class is created by the main Graphics class, eg Graphics->CreateSpriteFromTexture(base::Texture*)
EDIT:
When I needed to write some c++ dlls for use in python I used a library called pyCxx. The resulting dll basicly only exported one method, which created an instance of the "Module" class, which could then contain factory methods to create other classes etc.
The resulting dll could be imported in python just with "import [dllname]".
//dll compiled as cpputill.pyd
extern "C" void initcpputill()//only exported method
{
static CppUtill* cpputill = new CppUtill;
}
class CppUtill : public Py::ExtensionModule<CppUtill>
{
public:
CppUtill()
: Py::ExtensionModule<CppUtill>("cpputill")
{
ExampleClass::init_type();
add_varargs_method("ExampleClass",&CppUtill::ExampleClassFactory, "ExampleClass(), create instance of ExampleClass");
add_varargs_method("HelloWorld", &CppUtill::HelloWorld, "HelloWorld(), print Hello World to console");
initialize("C Plus Plus module");
}
...
class ExampleClass
...
static void init_type()
{
behaviors().name("ExampleClass");
behaviors().doc ("example class");
behaviors().supportGetattr();
add_varargs_method("Random", &ExampleClass::Random, "Random(), get float in range 0<=x<1");
}
How exactly does that work, and could I use it in a purely c++ enviroment to solve my problem here?

Easiest way to do this, IMHO, is to have a simple C function that returns a pointer to an interface described elsewhere. Then your app, can call all of the functions of that interface, without actually knowing what class it is using.
Edit: Here's a simple example.
In your main app code, you create a header for the interface:
class IModule
{
public:
virtual ~IModule(); // <= important!
virtual void doStuff() = 0;
};
Main app is coded to use the interface above, without any details on the actual implementation of the interface.
class ActualModule: public IModule
{
/* implementation */
};
Now, the modules - the DLL's have the actual implementations of that interface, and those classes don't even have to be exported - __declspec (dllexport) isn't needed. The only requirement for the modules is to export a single function, that would create and return an implementation of the interface:
__declspec (dllexport) IModule* CreateModule()
{
// call the constructor of the actual implementation
IModule * module = new ActualModule();
// return the created function
return module;
}
note: error checking left out - you'd usually want to check, if new returned the correct pointer and you should protect yourself from the exceptions that might be thrown in the constructor of the ActualModule class.
Then, in your main app, all you need is to simply load the module (LoadLibrary function) and find the function CreateModule (GetProcAddr function). Then, you use the class through the interface.
Edit 2: your RefCount (base class of the interface), can be implemented in (and exported from) the main app. Then all your module would need to link to the lib file of the main app (yes! EXE files can have LIB files just like DLL files!) And that should be enough.

You are re-inventing COM. Your RefCounted class is IUnknown. Your abstract class is an interface. A COM server in a DLL has an entrypoint named DllGetClassObject(), it is a class factory. There is lots of documentation available from Microsoft on COM, poke around a bit to see how they did it.

[Edit: whilst I was composing all this, Paulius Maruška edited his comment to say basically the same. So apologies for any duplication. Though I suppose you've now got one for spare :)]
Off the top of my head, and assuming Visual C++...
You need to use LoadLibrary to load a DLL in dynamically, then use GetProcAddress to retrieve from it the address of a function that will create the actual derived class that the DLL code implements. How you decide to do this precisely is up to you (the DLLs need finding, the way the expose their functionality needs specifying, etc.) so for now let's assume that plugins only provides new Sprite implementations.
To do this, decide on the signature of the function in the DLL that the main program will call to create one of these new sprites. This one looks suitable:
typedef Sprite *(*CreateSpriteFn)();
Then, from the main program, you'll have to load a DLL (again, how you find this DLL is up to you) and get the sprite creation function from it. I've decided that the sprite creation function will be called "CreateSprite":
HMODULE hDLL=LoadLibrary(pDLLName);
CreateSpriteFn pfnCreateSprite=CreateSpriteFn(GetProcAddress(hDLL,"CreateSprite"));
Then to actually create one of these, just call the function:
Sprite *pSprite=(*pfnCreateSprite)();
Once you are done with the DLL and there are no objects left that were created by it, you then use FreeLibrary to get rid of it:
FreeLibrary(hDLL);
To create a DLL that sports this interface, write the code for the derived class and so on then somewhere in the DLL code provide the CreateSprite function that the calling program needs, using the appropriate signature:
__declspec(dllexport)
extern "C"
Sprite *CreateSprite()
{
return new MyNewSprite;
}
The dllexport thing means that you can use GetProcAddress to pick this function up by name, and the extern "C" ensures that the name is unmangled and doesn't end up as "CreateSprite#4" or something like.
Two other notes:
GetProcAddress returns 0 if it couldn't find the function, so you can use this to scan through a list of DLLs (e.g., returned from FindFirstFile and friends) looking for DLLs that support the interface, and/or try to find multiple entry points and support multiple types per plugin.
if the main program is going to delete the sprite using the delete operator, this requires that both DLL and main program are built using the same runtime library, so that the main program's delete and the DLL's new are both using the same heap. You can work around this to some extent by having the DLL provide a DeleteSprite function, that deletes the sprite using the DLL's runtime library rather than the main program's, but you still have to take care about the rest of your program, so you may just want to force DLL writers to use the same runtime library as your program. (I wouldn't say you'd be in good company by doing this, but it's not uncommon. 3D Studio MAX requires this, for example.)

Perhaps you want to look into DLL Delay-Loading (http://www.codeproject.com/KB/DLL/Delay_Loading_Dll.aspx) - this will give you what you want without having to work too hard for it

Related

Correctly defining DLL-interfaces with C++11/14

I've read several times that passing STL objects like vector and string outside of a DLL boundary is bad practice because different compiler versions can generate different code for STL objects. Therefore, you should design a C-style interface and not pass STL objects at all. However, there are still some things unclear to me:
1. What is the 'boundary' of a DLL?
Is it right to say, that the boundary is where code is beeing compiled on DLL side? What if I define a .h file inside a DLL (f.e. to write a factory class) and use that header file in a different project? Is that .h file inside or outside the boundary of the DLL and why?
2. What is contained in a DLL?
Let' say I have a class Foo:
class Foo
{
public:
__declspec(dllexport) void f1(); //instantiates v1 inside function
private:
unique_ptr<vector<int>> v1 = nullptr;
}
If I only mark the function f1() with __declspec(dllexport), only this function should be contained in the DLL. How does the code inside f1() know what v1 is if v1 isn't contained in the DLL?
3. Passing objects out of a DLL-boundary using unique_ptr
I'm using unique_ptr almost everytime in my project. From what I understand, returning a unique_ptr from a DLL would be bad practice because unique_ptr is an STL object. How can I instantiate an object inside the DLL and return a unique_ptr to it?
4. Why does defining interfaces or using PIMPL help to define an DLL interface?
I still have to convert my STL classes to C-style objects. And in the project using the DLL, I would have to somehow wrap the C-style objects inside STL classes again. I don't see any advantage of using interfaces or PIMPL in this case.
Also, if I define an interface (class with pure virtual functions), wouldn't this have the same effect as just declaring the functions in my class with __declspec(dllexport)?
class IFoo
{
public:
virtual ~IFoo() = 0 {};
virtual void f1() = 0;
}
class Foo : public IFoo
{
public:
void f1();
//__declspec(dllexport) void f1(); //why use an interface if I can just declare the functions like this?
}
How is the DLL-STL problematic solved in modern C++ 11/14 libraries? Are there any modern open-source libraries that I can have a look at?
Unfortunately STL types aren't consistent across compilers. Even different versions of Visual Studio have differences.
The boundary is where the code is compiled. If you have an implementation in a header file in your library, then the compiler used to compile the EXE will compile the code. This is potentially very bad because what the code in the EXE thinks is the data is different to what the code in the DLL thinks is the data. (You need to look out for differences like this especially if you have #ifs in a struct definition and you need to be explicit about packing).
The only way to be sure is to define all your own types (being careful of packing) and not use STL. This is what DLL libraries usually do.
Interfaces can enable the user to dynamically link to the library. Using __declspec(dllexport) requires a static linking; that is the EXE has to link to the .lib generated when you compiled the DLL to be able to access all the functions. This means amongst other things you can't update the DLL without the EXE having to be recompiled (probably - you can get away with this in some circumstances, but it's not a good idea).
By dynamically linking you can update the DLL or add functionality to the DLL without relinking the EXE as long as you don't change your interfaces. The EXE might call LoadLibrary() on the DLL and GetProcAddress() to access one function that returns an interface. Everything else including data types passed as parameters are interfaces (i.e. contain only pure virtual functions) or simple structs. This is how the basic level of COM works.
To answer question 2, when you declare something as __declspec(dllexport) you are stating that this is part of the interface to the DLL - something that is accessible to the component that loads the DLL. Anything declared without __declspec(dllexport) should be present within the DLL but will not be available to be called/used by an external component.

c++ plugin : Is it ok to pass polymorphic objects?

When using dynamic libraries, I understand that we should only pass Plain Old Data-structures across boundaries. So can we pass a pointer to base ?
My idea is that the application and the library could both be aware of a common Interface (pure virtual method, = 0).
The library could instantiate a subtype of that Interface,
And the application could use it.
For instance, is the following snippet safe ?
// file interface.h
class IPrinter{
virtual void print(std::string str) = 0;
};
-
// file main.cpp
int main(){
//load plugin...
IPrinter* printer = plugin_get_printer();
printer->print( std::string{"hello"} );
}
-
// file plugin.cpp (compiled by another compiler)
IPrinter* plugin_get_printer(){
return new PrinterImpl{};
}
This snippet is not safe:
the two sides of your DLL boundaries do not use the same compiler. This means that the name mangling (for function names) and the vtable layout (for virtual functions) might not be the same (implementation specific.
the heap on both sides may also be managed differently, thus you have risks related to the deleting of your object if it's not done in the DLL.
This article presents very well the main challenges with binary compatible interfaces.
You may however pass to the other side of the mirror a pointer, as part of a POD as long as the other part doesn't us it by iself (f.ex: your app passes a pointer to a configuration object to the DLL. Later another DLL funct returns that pointer to your app. Your app can then use it as expected (at least if it wasn't a pointer to a local object that no longer exists) .
The presence of virtual functions in your class means that your class is going to have a vtable, and different compilers implement vtables differently.
So, if you use classes with virtual methods across DLL calls where the compiler used on the other side is different from the compiler that you are using, the result is likely to be spectacular crashes.
In your case, the PrinterImpl created by the DLL will have a vtable constructed in a certain way, but the printer->print() call in your main() will attempt to interpret the vtable of IPrinter in a different way in order to resolve the print() method call.

C++ / Share variable or send data from unmanaged to managed in the same DLL

I Have a mixed mode DLL containing a unmanaged part (DllMain) and a managed C++ part.
I calculate some folders in DllMain and I want to share/send data to the managed part when it is called.
I load DLL using LoadLibrary from another C++ program.
How can I share data or send data from DllMain to the managed part ?
I have to share/send some char*.
Thanks
You need to export a native function from the managed DLL, which native DLL can call upon.
Or, you can have an interface (C++ interface), powered by a CreateThisObject or similar, which will instantiate the derived-class (of interface). This interface, as well as the creation-function will be given by managed DLL, and native DLL will simply use it as normal C++ class.
Kind-of pseudo-code is presented below
// Export function only
EXPORT
int DoSomethingInManagedDLL(args);
// Export hidden class, through an interface
class IDLLHelper
{
virtual void DoSomething() = 0;
};
EXPORT IDLLHelper* CreateDLLHelper();
// Some class, known only to managed DLL
// This class, as well as above' interface is native
class DLLHelperImpl : public IDLLHelper
{
void DoSomething()
{
// actual code
}
};

C++ compiler independent DLLs using abstract interface

I followed the guide at CodeProject and built a DLL with an abstract interface and exported the factory functions using the extern "C" command along with __declspec(dllexport) and __cdecl and by doing this the article claims that the DLL becomes compiler independent with a clean interface. However when using the DLL on two different versions of g++ the non-standard ABI created the standard c++ problems with DLL calling. In addition to the CodeProject article I also used an article from MinGW in order to be able to create multiple instances of the class.
How is it then possible to make the DLL compiler independent? and if this is not possible, is it then possible to instantiate a class within a DLL and make the functions pure C but calling the C++ functions related to the instantiated class?
Have you tried to reproduce exactly the example that was given there? And what was the failure? You have to consider that not only your class, but any other class like std::string can't be used directly. That said, I wouldn't try to reinvent the wheel but use some kind of component framework like COM.
To answer your second part, consider this:
// internal class
struct X
{
void jump();
};
// compiler-independent C interface
struct X;
struct X* x_alloc(void);
void x_jump(struct X* x, float height);
void x_free(struct X* x);
This works. I have no idea what exactly you tried and what didn't work for you, there's just not enough info to tell.

invalid memory when using classes from a dll

this is the first time I've tried to export a class from a dll.
what I've done is:
- crated an interface (only pure virtual methods)
- implemented this interface in the dll with a class that wont be exported
- the class has a release method that calls delete on its this pointer
- created a Factory class with a static method that returns a pointer to the concrete class but as the interface. this class is exported.
- the deletion of the returned object is done by calling its release method.
I tuck all this from this tutorial about classes in dlls.
The problem is that when I use this dll in another project everything goes ok until I call the release function on the object.
Then it shows an assertion failed window with the message "_ASSERTE(_BLOCK_TYPE_IS_VALID(pHead->nBlockUse));"
Did this happened to anybody else?
I know this is as simple as forgetting to use std:: when you start C++ , but as I said I just started this.
Thanks!
Is your factory function defined in the header? If it is, and the new for creating the object is in the header then calling delete from within the DLL can cause this error. The factory function needs to be exported by the DLL, only the declaration must appear in the header.
For instance, your header should look line this:
class MyInterface
{
public:
virtual void DoSomething() = 0;
virtual ~MyInterface() {}
};
__declspec(dllexport) MyInterface * __stdcall MyInterfaceFactory();
The implementation of MyInterfaceFactory() must be contained within the DLL.
Thanks for your answers, and I'm sorry I started this for nothing!
The problem was very simple but hidden behind the interfaces , factory , and some other stuff.
I was returning a pointer to an object that was declared as static because it has to be a singleton. Then I was trying to release this object. BANG heap corruption!!
My singleton object shouldn't have a release function in the first place;
I'll solve this by extracting the release function in a separate interface , that will be implemented only by non static objects.