I'm trying to create a abstraction layer for platforms such as win32, mac os, linux, iOs etc.
I want this to be dynamically linked. On platforms that don't support this it shouldn't be a problem since from what I've seen everything that can be compiled as a dynamic library can be compiled as a static one as well with minimum impact on the code.
Now, to get to the point of this:
I created a interface named IThread and a class named CThread. I use a function named CreateThread that's defined with extern "C" to be able to export it and call it outside the library. The problem here is that in win32 for example there already is a function named CreateThread and thus I get a linker error. I understand the error and why it's appearing but I'm not sure of a good way to avoid this. I don't really like to use weird naming as qt uses like CreateQtThread.
Another idea I have would be is to create a thread manager/factory that creates instances of CThread but I'm not sure this would be a great idea.
What do you guys think about this? I'm asking because I don't want to rush on important organizing problems like this.
Thank you very much
I use a function named CreateThread that's defined with extern "C" to be able to export it and call it outside the library.
This is bad. I can't talk for other platforms, but on windows it's perfectly fine to export C++ functions. They are just get mangled, and you get some sanity checking in case someone changes the declaration. In fact, it's the only correct way to export a function that is C++. If you declare it as extern "C" you get no namespaces, no overloading, and someone who compiles with /EHsc will be in trouble if an exception escapes from your function.
Preferred solution: Do not declare them as extern "C", and put them in a namespace.
The only other solution: well, guess why all those C libraries prefix their functions with their_lib_prefix_function...
Your decision to use extern "C" is sound in my view because it allows access from other languages, compilers etc. But doing so means you can't use namespaces so you simply must prefix your functions with something to identify them as being from your library, a poor man's namespace if you will.
This is the compromise you must make if you want to use extern "C".
Well, I don't know whether you will like this as I know the C developers I worked with found it unaesthetic. But, it's very simple and prevents collisions like this. (More or less mentioned in this answer with the "their_lib_prefix_function" comment.)
So, whenever I was using C code, I used to basically 'namespace' my functions using an underscore. So, let's say your namespace is MegaAbstraction, then something like CreateThread becomes MegaAbstraction_CreateThread. Easy peasy. And no collisions, unless someone else has a namespace called MegaAbstraction in which case I recommend finding a namespace that's unlikely to be used by anyone else. ;)
Does your CreateThread use the stdcall calling convention (aka WINAPI)? If you use the cdecl calling convention, it should export the function name as _CreateThread and avoid the linkage conflict with the Win32 CreateThread function.
extern "C" _declspec(export) int _cdecl CreateThread(...
There is no "CreateQtThread" function in Qt, not even something similar. There's a QThread class, and it has constructors. If needed, you can put everything in a namespace.
Related
Is it possible to call a function in a C++ DLL from C code?
The function is not declared extern "C".
An ugly platform dependent hack that only works with Visual Studio is fine.
Calling conventions should not be a major issue, but how do I deal with name mangling.?
For instance with Visual Studio, a C++ function with signature void f() has the mangled name ?f##YAXXZ and that is not a legal C identifier.
(You don't need to tell me that I should declare the C++ function as extern "C".
I already know that. But I'm in a situation where I cannot change the C++ code.)
Wrap the offenging function in another C++ function, and declare it with extern "C". No need to create a special DLL for it, just include one C++ file in your project.
To make your compiler to statically link a function with a different exported name may be tricky. But you can always load the DLL with LoadLibrary and then use GetProcAddress.
You could investigate
LoadLibrary("path to dll");
to load the DLL and
GetProcAddress("?f##YAXXZ");
to grab a function pointer to the externally declared function.
I do not see any clean solution besides creating an additional dll written in C++ and exposing all interfaces via extern "C".
You could compile your C code using the same C++ compiler they used, then your C functions will be mangled using the same mechanism and everything will link seamlessly, and no-one will notice any difference.
If you must use a different compiler, then you'll have to manually load the dll using LoadLibrary and each function using GetProcAddress.
I would like to be able to use C/C++ functions from python using ctypes python module.
I have a function int doit() in the .c / .cpp file. When I try to load the shared library:
Frr=CDLL("/path/FoCpy2/libFrr.so")
Frr.doit(c_int(5))
i find it working really well when the .c variant is used. When C++ is called the good way to call this function is (found out using nm libFrr.so using nm -gC libFrr.so produces just plain doit()):
Frr._Z4doitv(c_int(5))
I have read on Stackexchange that there is no standard way to call C++ from python, and there is "nonstandard name mangling" issue. Is the "Z4" a part of that issue? I guess the nonstandard name mangling would appear for more advanced language features such as class methods, templates, but also for such basic functions? Is it possible to force using simple C function names in simple cases for the C++ code?
You can use extern "C" to make the functions "look like" C functions to the outside world (i.e., disable name-mangling). And yes, you are correct, name-mangling is needed mostly for the more complicated features and types of functions that C++ has, and the name-mangling scheme has never been standardized (nor the binary compatibility) and so it varies from compiler to compiler and between versions (but most main-stream compilers have settled to something permanent now, but still different between compiler-vendors). And the reason that mangling is also required for plain old free functions is because C++ supports overloading (same function names but with different parameters), and thus, the compilers will encode the parameter specification (e.g., types) into the mangled names. Of course, if you use extern "C" you lose all features for which name-mangling is needed, so, it more or less boils down to C functions only.
You can use extern "C" either on a per-function basis, like so:
extern "C" int doit();
Or for the overall header:
extern "C" {
// all the function declarations here ...
};
However, for Python specifically, I highly recommend that you use a library that allows you to construct Python classes and functions that are a reflection of your C++ classes and functions, that makes life a lot easier and hides away all this extern "C" business. I recommend using Boost.Python, see this getting started page, it makes exporting functions and classes to Python a breeze. I guess others would also recommend SWIG, but I have never used it.
Calling c++ library functions is always a mess, actually even if you're using C++ you have to use the same compiler, etc. to make sure it works.
The only general solution is to define your c++ functions as extern "C" and make sure you follow the involved limitations - see here for an explanation of it.
I have compiled a library that I have created with MinGW into an existing application using Borland 6 (I know its old but that's what it was made with). I have used implib to create the .lib file and imported it into my project. I have also added the paths to the dll and necessary header files.
When I try to compile I get a pile of Unnresolved external type errors. Have I missed out any steps of the importing process? Assuming I haven't and the issue is something like name-mangling how do I go about writing the interface in such a way that name mangling won't matter. I know it involves extern C but thats about the limit of my knowledge. There are only two classes that need to be accessed from outside the dll the remainder are all only used internally. I'm not sure how to use extern C with something that is entirely built with classes. I'm stil hopeful that it's my importing with borland 6.
extern "C" cannot be used for classes, only for free functions. So you have an option of writing a "C" interface to your class, where each function takes a pointer to your class and you would probably have create and destroy functions.
This is a way it is typically done, and your class could be forwardly declared as struct, which is the same as class, and then could even be used by applications written in C. You would normally put extern "C" only when __cplusplus is defined so there are normally #ifdef guards around it.
There is another option, if you only want your class to be used by C++ and you don't want to have to write a C interface for all your class methods.
Users of the DLL use an abstract interface and still use Create and Destroy methods (with extern "C") to create a pointer to the abstract interface, but then use the pointer in the normal C++ way. Of course ideally you will wrap this pointer in a smart pointer, e.g. a boost shared_ptr with a custom deleter that calls the Destroy method. (Users of the library should do that but you can provide a headers-only interface to do it).
There are a few other issues you would need to beware of if doing this, e.g. anything to do with run-time type information is likely to not work on the user-side, including exceptions. And once again your library could provide "open-source" C++ wrappers (compiled on the client side) to handle this in a more C++ way. A sort-of pImpl.
The name mangling is not standardized across compilers. Only expose extern C functions so that they are not name mangled. But this has a limitation that you cannot use object orient programming.
Another option is to implement COM objects as they are binary compatible.
I'd like to override the behavior of an std function, say std::time. Is it possible to call std::time and have it routed through my custom function?
The std namespace is off limits, generally speaking. Adding new functions, overloads, classes or anything else to the std namespace is **undefined behavior*.
The only exception is template specializations. You may provide specializations of functions in the std namespace. A function where this is often done is std::swap.
This sounds like a very bad idea. Kind of like redefining true or false. A better way would be to write your own wrapper function, say tim_time(), which may or may not call std::time() internally.
Instead of calling it std::time, route all calls that you might sometimes override through a different namespace.
namespace mystd{
using namespace std;
void time() { ... }
}
// ...
mystd::time(); // not std::time
mystd::copy(...); // calls std::copy, unless you override it like time()
Then the call to mystd::time will call the modified version of the function. If you call non-overridden function, for example, mystd::copy, it will be correctly resolved to the original std function.
Not portably. On the understanding that the standard doesn't define what happens, you can usually define whatever symbols and functions you like in namespace std, or link against a library that defines those symbols, or whatever. It's just undefined behaviour. So all you can do is suck it and see, and hope it doesn't break in the next release of your compiler.
That said, with most compilers it will probably mostly work, provided that you avoid a one-definition-rule clash with the "real" std::time. This is because most compilers don't actually do anything special with namespace std, and the header files and libraries they use to implement it are not really any different from header files and libraries you could write yourself.
Dima is absolutely right, though, that going off-standard like this is a almost always a very bad idea. Maybe if you're stuck in some debugging hell where you basically want to add logging to std::time, but can't, then it's worth thinking about. Otherwise don't go there. If you want to test some code, to see whether it works correctly at various times, then pass that code a parameter (or template parameter) specifying which time function it should call.
On some platforms, you can pull this off. In your source code, define the function, i.e.
extern "C" time_t time(time_t *value)
{
...
}
If you're lucky, the linker will bind your version of std::time more tightly than the one from the standard library. Of course, there's no guarantee that this will work, or be linked the way you want. And as a downside, you no longer have any access to the original std::time.
As everyone else has posted, this isn't portable behavior. I'm pretty sure it works on Linux. I'm also fairly certain it doesn't work on Windows (linker complains about the conflict).
I did used snippet found from Internet for this kind of linking, and it works. Now I would like to gain more understanding on this topic, i.e. what should I pay attention to if my C++ code is going to be export/linked by non-C++ code. Could somebody points me to any resources useful for this? Thanks.
The key concepts in native code interoperability are name mangling, and calling conventions.
But the real point here is that in general, if you want your code to be callable from other languages (you don't specify any in your question), you have to adopt a lowest-common-denominator approach. Usually that means avoiding objects and thinking functionally, wrapping your code in DLLs and using a C-style interface. You'll probably have to define your DLL's api functions using the STDCALL calling convention.
Also, if you use structures in your interface, you have to worry about structure packing. To get proper interop with Delphi using packed records, for instance, I think you'd have to set the struct member alignment to 1 byte in your C compiler.
use extern "C" functionality... see here. This allows interfacing at the "C" level which is probably much more "cross-platform/language".
This should pretty much explain it all: http://en.wikipedia.org/wiki/Compatibility_of_C_and_C++
Also.... In conjunction with Bob Moore's answer...you can prevent name mangling by using #ifdef
#ifdef __cplusplus
extern "C" {
#endif
/* function prototypes and global variable declarations */
#ifdef __cplusplus
}
#endif
That __cplusplus directive, found in <stddef.h> is defined as standard to the best of my knowledge...
Hope this helps,
Best regards,
Tom.