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.
Related
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.
What are the disadvantages of implementing C library in C++? The library is going to be used to build Windows application for regular PC using Visual Studio 2008 or newer. It is not clear why the specs state that it should be C library. I am guessing that what they want is plain C-API, not pure C lib. But my boss disagrees.
Anyway, what I want to do is to extern "C" all function declarations and use C++ in implementation files. I did some testing and everything worked just fine even when the application was compiled as C (by changing project option in Visual Studio).
I've seen people do that for, say, exposing STL collections to C programs. If you are sure that the library will only be used in environments with sane C/C++ compilers (say, VS and gcc only) I think this is a pretty safe thing to do from the technical perspective. N
ow, it sounds like you have some sort of outside requirement at play here, but obviously we can't comment on that. Might be worse double checking with the requirements source?
UPDATE: oh, I should mention that it will affect the DLLs that your library will require. Like the C++ runtime DLL will need to be loaded in addition to CRT.
The extern c is used like all the time to port some functionality from c to c++. For instance the new operator inturn calls the malloc() from std c. This is one good example of c library being given a c++ look. new operator makes it much more easy to allocate memory and in addition to that it also allows a lot of functionality like operator overloading which is not available in c. My guess would be to add more functionality to and to make neat interfaces.
If you are considering about disadvatanges then it might be related compiler specific problems where the ABL generated for a c++ program differs from that of the C and if the compiler is not able to differentiate between the two then you struck with it.
I am not sure if this is what you are seeking for, if not try this link it might be of some assistance.
http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=180
If they are going to use it for a C programm, i.e. the main() function is compiled by a C compiler, then you have to be very carefully with your C++ library. The problem is that the c programm will not execute any constructor for static variables. So you have to omit the usage of any static variables with constructor. This is easy for your library itself, but you have to check every call to a library C++ function if it relies on the existance of a static initialized variable (e.g. std::cout, std::cin etc.).
Is there a way to write a qt library such that I can then use it (statically linked is fine) in a C application?
My C code is huge, old and will not convert to C++ without an inordinate amount of work. I say this as other similar questions seem to answer "just make your C code a Qt app". That's not an option.
I hope I can write a qt library, and build it in a way that lets it be called from C (something alluded to in QLibrary documentation).
The symbol must be exported as a C
function from the library for
resolve() to work. This means that the
function must be wrapped in an extern
"C" block if the library is compiled
with a C++ compiler. On Windows, this
also requires the use of a dllexport
macro; see resolve() for the details
of how this is done.
Can someone confirm/deny that I can do this, and let me know how much "qt" I can put in the library?
I don't need a GUI but would like to use some of the SQL handling.
Cheers
Mike
You can put as much Qt in a library as you wish, including full UI capability. The rub is that since you want to access it from C code, you must provide your own access functions and your C functionality will be constrained to whatever level of access you provide.
You can even pass Qt object pointers between C and C++ but you'll need to cast them into something that C can compile -- either void * or preferably your own new type definition (such as C_QString *). To C code these pointers will be opaque, but they'll still be valid.
Over here I asked about translating an ASM file to C, and from the responses it looked like there was no reasonable way to do it. Fine. So one of the responses suggested I just make use of the functions as-is and be done with it. Sounds good.
But how?
Holy crap I've tried everything I can think of! I'm using a Microchip brand MCU (PIC18F4480) and a Microchip brand IDE (MPLAB IDE) and the ASM files are Microchip authored... so you'd think I'd find some way of making use of them! So far no luck at all.
I don't know anything about ASM (Assembly). I code in C++ and frankly that's not going to change. There has got to be a way to access the functions in the Microchip ASM files without rewriting all my code in a new language.
If anyone wants to take a look, the ASM files and application notes are here.
Looking at PIDInt.asm, it should be fairly straight-forward to call the functions from C/C++.
First, you declare extern variables for everything listed in VARIABLE DEFINITIONS:
extern unsigned char error0, error1; /* etc */
Then, you declare extern functions for all the things that have a "Function:" comment, taking no arguments and returning no result:
extern void Proportional(); // extern "C" for C++
To call one of them, you fill the input variables, call the function, and read the output variables.
I would expect you to need to somehow build an object (.o) file from the assembly code, and then link your C++ file with that object file. You are likely going to need to declare those functions as extern "C" to call them from C++.
Not sure about the details here, there might be issues with calling conventions between C++ and assembly, especially for a microcontroller such as the PIC.
Are you really using a full C++ feature set, i.e. objects, virtual functions, overloading, and so on, for a microcontroller? That's ... not bad, but I thought most PIC development was still in plain C (and assembly, of course).
The usual method is to use a build environment and tools that has an assembler as well as a C/C++ compiler. Compilers (and assemblers) take source files and produce an intermediate object file format. On Microsoft Windows, with Microsoft Tools, these would be .obj files.
A linker is then used to link the .obj files - which were potentially produced by a wide variety of languages - fortran, cobol, c++, c, objective-c, assembly etc, into a single application binary.
Object files are basically a collection of exported symbols, labeling little chunks of bytes, and unresolved symbols, labeling chunks of bytes that need to be patched during linking to point to something in a different object file.
Now, the usual problem - on the platforms Ive experienced which are not close to yours, are, c++ compilers are not made with any kind of cross language binary compatibility in mind. C compilers on the other hand, are. So c++ compilers make highly mangled symbols that incorporate all sorts of information about parameter and return types into the symbol names. This mechanism is what makes operator overloading possible.
Anyway, the crux is,
You need to build the asm files. If you dont have an assembler, you're outa luck. And it probably needs to come from the same vendor as your c/c++ toolset
You need to tell your c++ program the names of the external symbols. In a c compatible way. This is what header files are typically used for.
So create a header file to hold function declarations for the pid code and place Something like this in them:
extern "C" void PidMain(void);
Now, #include that header file in your c++ program, and ensure that the object files produced by the assembler are included in your environments link step and you should be golden.
There might be some kind of calling convention involved. Some environments have different standards as to the order things are pushed onto the stack, and/or who is responsible for stack cleanup. Most ms windows toolsets support at least a __pascal and __cdecl calling convention, so the declration would look like
extern "C" void __pascal PidMain(void);
I have no specific knowledge if there are multiple calling conventions in your specific environment. So I don't know how helpful this has been. Good luck I guess.
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++...