I have a C++ library that provides various classes for managing data. I have the source code for the library.
I want to extend the C++ API to support C function calls so that the library can be used with C code and C++ code at the same time.
I'm using GNU tool chain (gcc, glibc, etc), so language and architecture support are not an issue.
Are there any reasons why this is technically not possible?
Are there any gotcha's that I need to watch out for?
Are there resources, example code and/or documentation available regarding this?
Some other things that I have found out:
Use the following to wrap your C++ headers that need to be used by C code.
#ifdef __cplusplus
extern "C" {
#endif
//
// Code goes here ...
//
#ifdef __cplusplus
} // extern "C"
#endif
Keep "real" C++ interfaces in separate header files that are not included by C. Think PIMPL principle here. Using #ifndef __cplusplus #error stuff helps here to detect any craziness.
Careful of C++ identifiers as names in C code
Enums varying in size between C and C++ compilers. Probably not an issue if you're using GNU tool chain, but still, be careful.
For structs follow the following form so that C does not get confused.
typedef struct X { ... } X
Then use pointers for passing around C++ objects, they just have to be declared in C as struct X where X is the C++ object.
All of this is courtesy of a friend who's a wizard at C++.
Yes, this is certainly possible. You will need to write an interface layer in C++ that declares functions with extern "C":
extern "C" int foo(char *bar)
{
return realFoo(std::string(bar));
}
Then, you will call foo() from your C module, which will pass the call on to the realFoo() function which is implemented in C++.
If you need to expose a full C++ class with data members and methods, then you may need to do more work than this simple function example.
C++ FAQ Lite: "How to mix C and C++ code".
Some gotchas are described in answers to these questions:
[32.8] How can I pass an object of a C++ class to/from a C function?
[32.9] Can my C function directly access data in an object of a C++ class?
Main gotcha: exceptions can not be caught in C. If there is the possibility of an exception rising in the C++ code, either write your C code or your C++ wrappers very carefully. Conversely, exception like mechanisms (i.e., longjump) in the C code (as found in various scripting languages) are not required to invoke destructors for C++ objects on the stack.
you can mix C/C++ code. If your main() function in in C++, then you just need to make sure your c functions are declared
extern "C"
If your main is C, then you are probably OK except for static variables. Any constructors with your static variables are supposed to be called before main() start. This won't happen if C is your main. I you have a lot of static variables, the best thing to do is to replace static variables with singletons.
Related
My Problem is that I want to call some template function in C.
Therefore, I have declared an extern "C" function as a wrapper function, which calls this template function.
I know, that I need to compile the wrapper function, with the c++ compiler and then I get an object file, which I can link against a normal c-program.
The problem is, that I have written a header only C++ library, which I want to use in C, but in C I can't make the library header only anymore, once I need to link the C-program against the wrapper function.
So does there exist any way of generating a header only c-library, which calls the c++ template function? This method should work in GCC and it is absolutely no problem, if it is nonstandard, requires several pragmas, cli-parameters or something else.
I think, a possible solution would be to call gcc in C-mode on a file, where on a particular line, a switch from C to C++ inside the header file is possible. This C++ switch does the actual template call and than a switch back to the C-compiler is performed. Does some method exist?
e.g. like this:
#include <iostream>
#define SWITCH_TO_CPP_COMPILER() /*TODO: is this possible?*/
#define SWITCH_BACK_TO_C_COMPILER() /*TODO: is this possible?*/
#ifdef __cplusplus
extern "C" {
#endif
inline bool wrapper();
#ifdef __cplusplus
}
#endif
SWITCH_TO_CPP_COMPILER();
template<bool tmp>
constexpr bool template_func() noexcept {
return tmp;
}
inline bool wrapper() {
return template_func<true>();
}
SWITCH_BACK_TO_C_COMPILER()
#include <stdio.h>
int main() {
printf("%d\n", wrapper());
}
I have already looked at several questions, but they do not answer it:
C Wrapper for C++: How to deal with C++ templates?
how to write c wrapper around c++ code to expose class methods
Create a C wrapper around a C++ library that can be linked by a C linker
C wrapper around C++ library without unnecessary header files
The whole point of the C wrapper is to have the C++ compiler generate an object module for the instantiated template and the wrapper, and letting the C compiler be blissfully unaware of anything but the wrapper, known/invoked thorough an extern function declaration.
This thing cannot be header-only: a header is brutally included in the file that uses it, and that file is going to be processed by a C compiler, which then would have to be able to parse/instantiate the C++ template besides the wrapper function, and this is obviously not possible. Parsing C++ is already complex as it is, requiring to switch to a different language in mid-air is completely bonkers.
If you want to use your library into a "C proper" program you have to have an extra TU compiled by a C++ compiler. Otherwise, since however you think about this you need some C++ compiler being able to compile your template, just compile everything in C++ and, if you prefer, just use the C subset for the rest of the files.
You already have a dependency from a C++ compiler and most probably from the C++ standard library, so this isn't going to change much besides compilation speed in the grand scheme of things.
This in mind what Matteo wrote in his answer:
Convinced that what OP wants is impossible, I tried to find a substantive argument.
I compared the "Phases of translation" for C and C++.
The first phases concerning pre-processing look quite similar but starting with phase 7 (compilation) it becomes quite different.
I hardly doubt that any compiler can switch from C to C++ and back in the mid of a translation unit (if it is standard conform).
So basically I am trying to integrate a custom C library into an existing C++ project. I have various C++ objects that will need to be stored/loaded into a C DB and interface with various C functions. I need to convert my C++ objects into C structs, and back again. I have made progress, but am running into memory allocation issues.
I know I haven't included any code here, but I am just wondering if there are any general tips for this task? I have seen the void* used in extern "C" for generic C++ objects, but I really need to load/save data from/to C++ objects and C structs.
If I haven't worded this correctly, please ask!
Use extern "C" to declare your C structures:
extern "C" {
struct some_c_struct {
int field1;
char *p;
};
};
Then, in your C++ code you can use some_c_struct just like any other C++ class or struct, with guaranteed C compatibility, and successfully pass them to and from the C code library that you're using.
Practically speaking, the extern "C" declaration isn't needed, but all the language lawyers demand it. Additionally, your struct cannot use any C++-specific features, like virtual functions.
I know I can include C methods inside a C++ project using the extern "C" thing. But lets us now suppose that I'm thinking in creating a C++ project that would use quite a lot of C methods coming from both libraries made by me as well as libraries made by other people/companies whose developing details and compilation specifications I'm simply not aware of.
Is it possible that some of this methods of C libraries, with unknown compilation and configuration details, could not be included in my C++ project with extern "C"? Or are all C methods necessarily 100% compatible with C++ code insofar extern "C" is used?
It's possible that some of the functions exported by C use names that collide with C++ keywords. You wouldn't be able to declare those using extern "C".
Functions exported by assembler could even use names that conflict with C keywords.
Those and functions declared static can still be called via function pointer, as long as the library gives you a way to get one.
Headers might not be parse-able in C++ mode for the same reasons -- things like the restrict keyword.
Other than naming issues, C++ has full support for the C calling convention. That's what extern "C" is all about.
C has constructs for interfaces that are not compatible with C++, in particular variable length arrays. In modern C you would write
void matMult(size_t n, size_t k, size_t m, double A[n][k], double B[k][m], double C[n][m]);
this interface can not be included as such in C++ compilation units.
Although rather unlikely, one possible issue that might arise with extern "C" in-place is when a function pointer declared extern "C" points to a C++ function that is not declared extern "C". See the last part of this page for more details.
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.
Can I have a project that has some parts written in c and other parts written in c++ ?
Is this possible ?
Yes.
If you have control of the C code, then inside your C header files you should have:
#ifdef __cplusplus
extern "C" {
#endif
// normal header stuff here
#ifdef __cplusplus
};
#endif
That way they can be properly interpreted when included by both C and CPP code files.
If you include C code in your C++ via a header, and it doesn't include the code above, and you don't have enough control of it to make the necessary modifications, be sure to use e.g.
extern "C" {
#include "some_c_header.h"
};
Note that you can use this as a modifier for declarations too, e.g.:
extern "C" void someFunction();
Note that C++ has this mechanism for importing C functionality. C doesn't have one for importing C++, and trying to include C++ code in a C compilation unit will pretty quickly end in a bunch of error messages. One consequence of this is that your main function will need to be C++.
You need a compiler that can compile both languages (I have not heard of a C++ compiler that cannot do that), or compile them with a fitting compiler each and link them (in which case the answer of #sje397 applies). There is a good explanation on the subject in the C++ FAQ Lite.
How to mix C and C++:
http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html
Yes it is very much possible. In fact usually legacy systems refactored later on usually have legacy code which is C as the core but with C++ wrappers on top of it.
Yes you can. C++ is mainly a superset of C. There might be some exceptions, but for the most part it is quite normal to include stuff written in C in your C++ projects.
Yes, you can have a project with both C and C++ code.