Can I organize classes in DLLs? [closed] - c++

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
I admit that this question sounds quite general. But after all, exporting classes from DLLs is a general and difficult topic, and frankly, I am currently confused on a quite general level.
The short question: How do object-oriented programming in C++ and DLLs fit together?
The long question: After reading this and this, I was slightly disappointed and confused because I wonder how object-oriented programming can work with DLLs if the DLL borders do not allow objects to be shared (assuming that two DLLs have used different compilers or compiler versions). The only options for exporting classes are these (as explained here or here):
export create and delete methods (C style, danger of dangling pointers, no objects as parameters, ugly)
export a pure virtual class and a factory function which creates an instance of the actual implementation class derived from the pure virtual class (needs inheritance, object deletion needs to be taken care of)
For example, I'd like to put common utility classes in one DLL, which I then use in several classes in other DLLs, which are themselves used in other DLLs. How can I do this? Is this an ill-defined way to organize my classes?
Bonus question: If I export a class having a pointer to implementation, is this equivalent to exporting a pure virtual class and a factory function? Or do the exported member functions have to be virtual?
EDIT: If it matters, I am on Windows 7 using Visual Studio 2010. Migrating vom an older Visual Studio made me sensitive to this problem.

TL;DR : it depends.
The Simple Case
When the two DLLs (or a DLL and an executable) have been built with the same compiler and compiler version, and they use the same flavor of runtime (debug or release), and they link against the dynamic version of the runtime, you can do whatever you want. Delete across DLL boundaries for example.
The Less Simple Case
When one DLL link against a debug runtime and the other link against a release runtime, things get more complicated. This is because the debug runtime have different STL templates, for debugging purposes. For example, you can't manipulate an std::vector allocated from a debug DLL in the release DLL, and vice-versa. As long as you confine these STL templates into the right DLL, things should work. Obviously, you'll run into problems if you expose different ABI's yourself, for example by declaring a member in a #ifndef NDEBUG block.
You may have to force things a little bit with _CRT*defines for this to work, depending on what templates the debug DLL uses.
You should also create and destroy objects from the same DLL.
The Terrible (a.k.a. Real World) Case
When compiler versions don't match, on when at least one DLL is linked with a static runtime.
You'll run into a ton of ABI problems. The only safe thing to do is to rely (extensively) on the C ABI via extern "C". This is also probably what you want to do if you load the DLL at runtime.
A good thing to do at this point:
Write your DLL in C++
Do not expose (dllexport) anything using the C++ ABI.
Write a thin C wrapper around your C++ code.
Expose this C API with __declspec(dllexport)
Write a header-only C++ wrapper around the exposed C API.
Clients will then use your header-only wrapper, so every call to your DLL code will be made using the C ABI, which is extremely stable and unlikely to break.

It's been a long time since I wrote one of the questions you linked, but let me try to help.
The short question: How do object-oriented programming in C++ and DLLs fit together?
That depends entirely on what your objects are exposing. If your objects are returning plain-C values, you should be okay. If your objects are returning POD classes containing plain-C values, you should also be okay. The headaches I was trying unsuccessfully to solve in that question/answer pair were almost entirely STL related.
To answer the natural followup question, the STL plays very badly with DLLs. C++ classes have innate cross-compiler compatibility issues due to different packing, member reordering, etc. The STL adds an extra layer of potential incompatibility because, when built into a debug DLL, extra members can be added.
For example, I'd like to put common utility classes in one DLL, which I then use in several classes in other DLLs, which are themselves used in other DLLs. How can I do this?
After failing to pass STL types successfully, I ultimately wrapped my C++ classes in a layer that translated them to and from their C counterparts. Where possible, I returned basic datatypes. Where I had to allocate memory (string, vector, etc.) I ended up with c-style create/delete functions. I believe I still exposed a pure virtual interface to protect as many implementation details as possible; I just didn't attempt to pass any STL objects directly across the DLL boundary.
If I export a class having a pointer to implementation, is this equivalent to exporting a pure virtual class and a factory function? Or do the exported member functions have to be virtual?
If I understand the question correctly, you want to do both.
struct MyDLL
{
virtual void DoSomething() = 0;
virtual int AddSomething(int argument1, int argument2) = 0;
}
extern "C" __declspec(dllexport) MyDLL* GetMyDLL();
Now your caller can call GetMyDLL and have a pointer to your class, and you can safely implement the virtual functions behind-the-scenes without worrying about your caller seeing what you're doing.

Related

How to include classes of a DLL?

I'm new to using DLL's in C++ and I am wondering how to sucessfully load and use classes contained in a DLL without getting a "corrupted stack", a "null pointer" or any application crash ^^. This is a bit confusing to me for now.
Even if it might be safer I don't want to use interface class because it seems too complicated to use. I know that I should have the same include in both DLL and application to prevent crashes. That means that my include file should mention members name.
Here is the problem :
I want to distribute my software (DLL + include file) and I don't want
my customers to see the architecture of my project. But the only class
I want to export from my DLL has as member, objects from other
classes. So my class is dependent of other classes and so on in
cascade.
Is it possible to provide only one include file of one class with just useful methods without having risks of crashes ? If no, what solutions might fit my needs ?
Thanks
FIrst of all, if you use the same include in DLL and in the application using it, if both were compiled with the same compiler and compatible settings, and both use the same runtime library (DLL one, not statically linked), you should have none of the problem you fear.
If you want to hide details of your DLL and provide an alterered, simplified header to the DLL users, you work on your own risk. For example, if there are data members missing (even private ones) of if there are virtual functions missing (even private ones), then it might probably crash, or worse, corrupt something without being noticed. So I'd strongly advise you not to consider this approach unless you're very very experienced with the assembler generated by your compiler.
If you want to hide implementation details of your class, the best approach would probably to design your library around the PIMPL idiom.

Can C++ code reliably interact with other C++ code?

In C, I'm used to being able to write a shared library that can be called from any client code that wishes to use it simply by linking the library and including the related header files. However, I've read that C++'s ABI is simply too volatile and nonstandard to reliably call functions from other sources.
This would lead me to believe that creating truly shared libraries that are as universal as C's is impossible in C++, but real-world implementations seem to indicate otherwise. For example, Node.js exposes a very simple module system that allows plain C++ functions (without extern "C") to be exported dynamically using the NODE_SET_METHOD function.
Which elements of a C++ API are safe to expose, if any, and what are the common methods of allowing C++ code to interact with other pieces of C++ code? Is it possible to create shared libraries that can expose C++ classes? Or must these classes be individually recompiled for each program due to the inconsistent ABI?
Yes, C++ interop is difficult and filled with traps. Cold hard rules are that you must use the exact same compiler version with the exact same compiler settings to build the modules and ensure that they share the exact same CRT and standard C++ libraries. Breaking those rules tend to get you C++ classes that don't have the same layout on either end of the divide and trouble with memory management when one module allocates an object using a different allocator from the module that deletes the object. Problems that lead to very hard to diagnose runtime failure when code uses the wrong offset to access a class member and leaks memory or corrupts the heap.
Node.js avoids these problems by first of all not exporting anything. NODE_SET_METHOD() doesn't do what you think it does, it simply adds a symbol to the Javascript engine's symbol table, along with a function pointer that's called when the function is called in script. Furthermore, it is an open source project so building everything with the same compiler and runtime library isn't a problem.
This
For example, Node.js exposes a very simple module system that allows
plain C++ functions (without extern "C") to be exported dynamically
using the NODE_SET_METHOD function.
Is wrong, you can see that they are using an an extern "C" there in the init() function, which is clearly what node.js is calling which is then forwarding the function on to which ever C++ function they want, which isn't exposed.
As explained in this question How does an extern "C" declaration work? - When the compiler compiles the code, it mangles the function names, class names and namespace names. The reason it does this is because there can very easily be name clashes, for instance with overloaded functions.
Read about it more here: http://en.wikipedia.org/wiki/Name_mangling
The only way to refer and lookup a function is if the extern "C" declaration is used, which forces the compiler to not mangle the name. I.e. in the example above, the function init will be called init where as the function foo will be called something like _ugAGE (I made this up, because it doesn't matter, it isn't for human consumption)
In summary, you can expose any C++ to any other language, but the entry point to the library must be one or more extern "C"'d global functions as they are the only way to refer to an unmangled name.
Neither the C nor the C++ standards define an ABI. That is entirely left up to the implementation. The reason it's harder to get shared/dynamic libraries working for C++, is that C++ added things like classes, polymorphism, templates, exceptions, function overloading, STL, ...
So, the real source of information for you, is your compilers' documentation, as well as a corresponding set of guidelines for your library API to avoid any issues with any of the implementations your library will be built for. It's harder in C++ (the set of guidelines will likely be quite a bit bigger than for C, and you might have to work with a subset of C++), but not impossible.

What problems can appear when using G++ compiled DLL (plugin) in VC++ compiled application?

I use and Application compiled with the Visual C++ Compiler. It can load plugins in form of a .dll. It is rather unimportant what exactly it does, fact is:
This includes calling functions from the .dll that return a pointer to an object of the Applications API, etc.
My question is, what problems may appear when the Application calls a function from the .dll, retrieves a pointer from it and works with it. For example, something that comes into my mind, is the size of a pointer. Is it different in VC++ and G++? If yes, this would probably crash the Application?
I don't want to use the Visual Studio IDE (which is unfortunately the "preferred" way to use the Applications SDK). Can I configure G++ to compile like VC++?
PS: I use MINGW GNU G++
As long as both application and DLL are compiled on the same machine, and as long as they both only use the C ABI, you should be fine.
What you can certainly not do is share any sort of C++ construct. For example, you mustn't new[] an array in the main application and let the DLL delete[] it. That's because there is no fixed C++ ABI, and thus no way in which any given compiler knows how a different compiler implements C++ data structures. This is even true for different versions of MSVC++, which are not ABI-compatible.
All C++ language features are going to be entirely incompatible, I'm afraid. Everything from the name-mangling to memory allocation to the virtual-call mechanism are going to be completely different and not interoperable. The best you can hope for is a quick, merciful crash.
If your components only use extern "C" interfaces to talk to one another, you can probably make this work, although even there, you'll need to be careful. Both C++ runtimes will have startup and shutdown code, and there's no guarantee that whichever linker you use to assemble the application will know how to include this code for the other compiler. You pretty much must link g++-compiled code with g++, for example.
If you use C++ features with only one compiler, and use that compiler's linker, then it gets that much more likely to work.
This should be OK if you know what you are doing. But there's some things to watch out for:
I'm assuming the interface between EXE and DLL is a "C" interface or something COM like where the only C++ classes exposed are through pure-virutal interfaces. It gets messier if you are exporting a concrete class through a DLL.
32-bit vs. 64bit. The 32-bit app won't load a 64-bit DLL and vice-versa. Make sure they match.
Calling convention. __cdecl vs __stdcall. Often times Visual Studio apps are compiled with flags that assuming __stdcall as the default calling convention (or the function prototype explicitly says so). So make sure that the g++ compilers generates code that matches the calling type expected by the EXE. Otherwise, the exported function might run, but the stack can get trashed on return. If you debug through a crash like this, there's a good chance the cdecl vs stdcall convention was incorrectly specified. Easy to fix.
C-Runtimes will not likely be shared between the EXE and DLL, so don't mix and match. A pointer allocated with new or malloc in the EXE should not be released with delete or free in the DLL (and vice versa). Likewise, FILE handles returned by fopen() can not be shared between EXE and DLL. You'll likely crash if any of this happens.... which leads me to my next point....
C++ header files with inline code cause enough headaches and are the source of issues I called out in #3. You'll be OK if the interface between DLL And EXE is a pure "C" interface.
Name mangling issues. If you run into issues where the function name exported doesn't match because of name mangling or because of a leading underscore, you can fix that up in a .DEF file. At least that's what I've done in the past with Visual Studio. Not sure if the equivalent exists in g++/MinGW. Example below. Learn to use "dumpbin.exe /exports" to you can validate your DLL is exporting function with the right name. Using extern "C" will also help fix this as well.
EXPORTS
FooBar=_Foobar#12
BlahBlah=??BlahBlah##QAE#XZ #236 NONAME
Those are the issues that I know of. I can't tell you much more since you didn't explain the interface between the DLL and EXE.
The size of a pointer won't vary; that is dependent on the platform and module bitness and not the compiler (32-bit vs 64-bit and so on).
What can vary is the size of basically everything else, and what will vary are templates.
Padding and alignment of structs tends to be compiler-dependent, and often settings-within-compiler dependent. There are so loose rules, like pointers typically being on a platform-bitness-boundary and bools having 3 bytes after them, but it's up to the compiler how to handle that.
Templates, particularly from the STL (which is different for each compiler) may have different members, sizes, padding, and mostly anything. The only standard part is the API, the backend is left to the STL implementation (there are some rules, but compilers can still compile templates differently). Passing templates between modules from one build is bad enough, but between different compilers it can often be fatal.
Things which aren't standardized (name mangling) or are highly specific by necessity (memory allocation) will also be incompatible. You can get around both of those issues by only destroying from the library that creates (good practice anyway) and using STL objects that take a deleter, for allocation, and exporting using undecorated names and/or the C style (extern "C") for exported methods.
I also seem to remember a catch with how the compilers handle virtual destructors in the vtable, with some small difference.
If you can manage to only pass references of your own objects, avoid externally visible templates entirely, work primarily with pointers and exported or virtual methods, you can avoid a vast majority of the issues (COM does precisely this, for compatibility with most compilers and languages). It can be a pain to write, but if you need that compatibility, it is possible.
To alleviate some, but not all, of the issues, using an alternate to the STL (like Qt's core library) will remove that particular problem. While throwing Qt into any old project is a hideous waste and will cause more bloat than the "boost ALL THE THINGS!!!" philosophy, it can be useful for decoupling the library and the compiler to a greater extent than using a stock STL can.
You can't pass C runtime objects between them. For example you can not open a FILE buffer in one and pass it to be used in the other. You can't free memory allocated on the other side.
The main problems are the function signatures and way parameters are passed to library code. I've had great difficulty getting VC++ dll's to work in gnu based compilers in the past. This was way back when VC++ always cost money and mingw was the free solution.
My experience was with DirectX API's. Slowly a subset got it's binaries modified by enthusiasts but it was never as up-to-date or reliable so after evaluating it I switched to a proper cross platform API, that was SDL.
This wikipedia article describes the different ways libraries can be compiled and linked. It is rather more in depth than I am able to summarise here.

Exporting classes to a dll in a portable way, without using interfaces?

I have a question about shared libraries/.dlls and class importing/exporting. From what I have understood after some research the two ways to do it is as follows:
Just using __declspec(dllexport/dllimport) before the class and praying that the different compiler versions mangle the names in the same way, and accept the fact that your .dll will not be useable by different compilers.
Use pure virtual classes in the dll as interfaces. Then all the classes that would need exporting would inherit from them and should implement the virtual functions. What the .dll would export in this case is just "factory" Construct/Destruct functions which would create and release the objects.
These are the only two ways I know. The first is a no-no since it offers 0 portability. The second, though convenient and a good programming design for a .dll that accomplishes a purpose starts to be annoying when you realize that you need to have a different constructor function for every different constructor, can only use POD types as parameters and you lose many advantages of C++ classes such as overloaded functions and default function arguments.
For a .dll that is supposed to offer a library to the user, a collection of classes for example even the second way becomes really inconvenient. So I am wondering what is the solution here? Just compile a different .dll with the first way for each major compiler? How do the shared libraries version of big libraries work? For example wxWidgets does offer a .dll version too. How do they achieve normal usage of classes by the end user of the .dll avoiding the interface solution?
Solution with having separate DLL for each compiler version works. At the same time it is still not an official feature. You will never know if next service pack will break the compatibility or not, nobody will give you exact list of compiler/linker keys that will maintain/break the compatibility, etc. I heard reliable rumors that Windows8 finally implemented this in the right way.
By the way Visual Studio 2012 Release Candidate can be still downloaded from: http://msdn.microsoft.com/en-us/vstudio/bb984878.aspx. Maybe you should try it?

How to implement monkey patch in C++?

Is it possible to implement monkey patching in C++?
Or any other similar approach to that?
Thanks.
Not portably so, and due to the dangers for larger projects you better have good reason.
The Preprocessor is probably the best candidate, due to it's ignorance of the language itself. It can be used to rename attributes, methods and other symbol names - but the replacement is global at least for a single #include or sequence of code.
I've used that before to beat "library diamonds" into submission - Library A and B both importing an OS library S, but in different ways so that some symbols of S would be identically named but different. (namespaces were out of the question, for they'd have much more far-reaching consequences).
Similary, you can replace symbol names with compatible-but-superior classes.
e.g. in VC, #import generates an import library that uses _bstr_t as type adapter. In one project I've successfully replaced these _bstr_t uses with a compatible-enough class that interoperated better with other code, just be #define'ing _bstr_t as my replacement class for the #import.
Patching the Virtual Method Table - either replacing the entire VMT or individual methods - is somethign else I've come across. It requires good understanding of how your compiler implements VMTs. I wouldn't do that in a real life project, because it depends on compiler internals, and you don't get any warning when thigns have changed. It's a fun exercise to learn about the implementation details of C++, though. One application would be switching at runtime from an initializer/loader stub to a full - or even data-dependent - implementation.
Generating code on the fly is common in certain scenarios, such as forwarding/filtering COM Interface calls or mapping OS Window Handles to library objects. I'm not sure if this is still "monkey-patching", as it isn't really toying with the language itself.
To add to other answers, consider that any function exposed through a shared object or DLL (depending on platform) can be overridden at run-time. Linux provides the LD_PRELOAD environment variable, which can specify a shared object to load after all others, which can be used to override arbitrary function definitions. It's actually about the best way to provide a "mock object" for unit-testing purposes, since it is not really invasive. However, unlike other forms of monkey-patching, be aware that a change like this is global. You can't specify one particular call to be different, without impacting other calls.
Considering the "guerilla third-party library use" aspect of monkey-patching, C++ offers a number of facilities:
const_cast lets you work around zealous const declarations.
#define private public prior to header inclusion lets you access private members.
subclassing and use Parent::protected_field lets you access protected members.
you can redefine a number of things at link time.
If the third party content you're working around is provided already compiled, though, most of the things feasible in dynamic languages isn't as easy, and often isn't possible at all.
I suppose it depends what you want to do. If you've already linked your program, you're gonna have a hard time replacing anything (short of actually changing the instructions in memory, which might be a stretch as well). However, before this happens, there are options. If you have a dynamically linked program, you can alter the way the linker operates (e.g. LD_LIBRARY_PATH environment variable) and have it link something else than the intended library.
Have a look at valgrind for example, which replaces (among alot of other magic stuff it's dealing with) the standard memory allocation mechanisms.
As monkey patching refers to dynamically changing code, I can't imagine how this could be implemented in C++...