I've been reading questions on Stack Overflow for a few weeks now... this'll be my first question.
So recently I've looked into making C access/manipulate a C++ class. I understand that ideally one shouldn't compile components in C and C++ separately under normal circumstances, but this isn't an option at the moment.
I looked into 3 Tutorials regarding being able to port/use a C++ in C. They are:
"A Guide to C++ and C Interoperability" on DevX
"Mixing C and C++ Code in the Same Program" article on Sun's site.
"[32] How to mix C and C++" on Parashift
First, what I already know:
You must use extern "C" to avoid
C++ function name mangling.
You need callback prototypes that are C-compatible.
G++ must compile the C++ into .o files, GCC compiles the C-specific code into .o files, then link both after.
As a result, the project I have is made of 4 files:
foo.h, header that'll list all prototypes that C/C++ will see (classes invisible to C of course)
foo.cpp containing the Foo class, and a set of C-compatible callback functions to invoke the class and methods.
fooWrap.c a set of C-specific wrappers that reference the callback functions in foo.cpp.
main.c the test method.
Here's the code I typed up, then my questions:
FOO.H
// Header File foo.h
#ifndef FOO_H
#define FOO_H
//Content set inside this #ifdef will be unseen by C compilers
#ifdef __cplusplus
class Foo
{
public:
void setBar(int);
void printBar();
private:
int bar;
};
#endif
//end of C++-only visible components.
#ifdef __cplusplus
extern "C" {
#endif
//Stuff made to be seen by C compilers only. fooWrap.c has definitions.
#if defined(__STDC__) && !defined(__cplusplus)
typedef struct Foo Foo;
//C-wrappers for C++ callback functions.
Foo * c_NewFoo();
void c_SetFooBar( Foo *, int);
void c_PrintFooBar( Foo *);
#endif
//These are the functions C++ AND C can both use...
Foo * newFoo(); //allocates the memory for Foo class, pass address back.
void setFooBar( Foo * , int ); //set internal contents of Foo object.
void printFooBar ( Foo * ); //print internal contents of Foo object.
#ifdef __cplusplus
}
#endif
#endif /*FOO_H*/
TEST.C
#include "foo.h"
// test.c test file for wrappers that manipulate C++ objects.
main()
{
//looks very C++ like... this makes C-Programmers cringe doesn't it?
Foo * cfoo = c_NewFoo();
Foo * cppfoo = newFoo();
//using the C-specific wrappers.
c_SetFooBar(cfoo,31415);
c_PrintFooBar(cfoo);
//using the C/C++ callback functions to Foo objects.
setFooBar(cppfoo,9001);
printFooBar(cppfoo);
}
So I split the definitions up into the 4 files as I mentioned before... and it compiles fine. But here's what I don't quite get.
Why do the sun and parashift articles suggest to create C-Wrappers whose only code is to pass it's arguments onto C/C++ compatible functions who then call C++ specific code?
i.e.
//in Stuff.cpp
void CallCppStuff () { /* c++ stuff */ }
//in wrapStuff.c
wrapCppStuff() { CallCppStuff() }
As you can see from my test.c file... I'm able to call up either set of calls without a problem (as far as I can tell). Are the c_ wrappers needless overhead, or am I missing the whole point of them altogether? My only guess has something to do with pointer addressing schemes of C/C++... but I'm not sure.
Also, I imagine there are more issues beyond just this... but those 3 sites are all I could find specific to this problem. So if there are any other glaring oversights on my part, I'd appreciate their mentioning.
Thanks in advance for any help/advice,
CX
If you have a series of functions that are not object-orientated or in a namespace, there's no need to wrap them again. Your c_ series of functions are redundant.
Any C++ function that is extern C, has global (i.e., not namespace/static member) linkage, and only takes C-compat datatypes (normally we use opaque pointers like you have), then it doesn't need to be wrapped. That is the wrapping function. C++ uses member functions directly and doesn't need to use them, and they certainly don't need to be duped.
Related
I'm writing a C program (myapp) which needs to use a particular api; the api is written in C++. I've worked with C and C++, but never both at once, and I'm getting confused.
So, the api provides the following directory, which I've placed in a folder called include, at the same level as my makefile:
libmyapi.a
api/api.h
My main source file is src/myapp.c, and it includes the api using #include "api/api.h".
My make command is (plus some flags, which I haven't listed because I don't think they're relevant here):
gcc -Linclude -lmyapi -Iinclude src/myapp.c -o lib/myapp.sp -lrt
The problem I'm having is that the api.h file contains references to namespaces etc. Eg at one point it has:
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
and obviously the C compiler doesn't know what this means.
So, I assumed I'd need to compile using a C++ compiler, but then someone said I didn't, and I could just "wrap" the code in "extern 'C'", but I don't really understand. Having read around online, I'm not any further on.
Do I need to compile in C++ (ie using g++)?
Do I need to "wrap" the code, and what does that mean? Do I just do
#ifdef __cplusplus
extern "C" {
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
}
#endif
or do I just wrap the lines
namespace MyAPI {
namespace API {
and then their corresponding }}?
The header file calls other header files, so potentially I'll need to do this in quite a lot of places.
So far I've got errors and warnings with all the variations I've tried, but I don't know whether I'm doing the wrapping wrong, setting g++ compiler flags wrong, using the wrong compiler, or what! If I know the method to use, I can at least start debugging. Thank you!
You can write a small C++ program that creates a C binding for the API.
Gvien this API:
namespace MyAPI {
namespace API {
typedef SimpleProxyServer SimpleConnection;
}
}
you can create c_api.h
#ifdef __cplusplus
extern "C" {
#endif
struct api_handle_t;
typedef struct api_handle_t* api_handle;
api_handle myapi_api_create();
void myapi_api_some_function_using_api(api_handle h);
void myapi_api_destroy(api_handle h);
#ifdef __cplusplus
}
#endif
and c_api.cpp
#include "c_api.h"
#include <myapi/api/stuff.hpp>
struct api_handle_t
{
MyAPI::API::SimpleConnection c;
};
api_handle myapi_api_create()
{
return new api_handle_t;
}
void myapi_api_some_function_using_api(api_handle h)
{
//implement using h
}
void myapi_api_destroy(api_handle h)
{
delete h;
}
compile that with a C++ compiler and include the c_api.h file in the C project and link to the library you created with the C++ compiler and the original library.
Basically, your C++ library needs to export a pure C API. That is, it must provide an interface that relies solely on typedef, struct, enum, preprocessor directives/macros (and maybe a few things I forgot to mention, it must all be valid C code, though). Without such an interface, you cannot link C code with a C++ library.
The header of this pure C API needs to be compilable both with a C and a C++ compiler, however, when you compile it as C++, you must tell the C++ compiler that it is a C interface. That is why you need to wrap the entire API within
extern "C" {
//C API
}
when compiling as C++. However, that is not C code at all, so you must hide the extern "C" from the C compiler. This is done by adding the preprocessor directives
#ifdef __cplusplus1
extern "C" {
#endif
//C API
#ifdef __cplusplus1
}
#endif
If you cannot change your libraries header, you need to create a wrapper API that offers this pure C API and calls through to the respective C++ code.
How do I call C++ functions from C?
By writing calling functions whose declarations are valid in the common subset of C and C++. And by declaring the functions with C language linkage in C++.
The problem I'm having is that the api.h file contains references to namespaces
Such header is not written in common subset of C and C++, and therefore it cannot be used from C. You need to write a header which is valid C in order to use it in C.
Do I need to compile in C++ (ie using g++)?
If you have function definitions written in C++, then you need to compile those C++ functions with a C++ compiler. If you have C functions calling those C++ functions, then you need to compile those C functions with C compiler.
A minimal example:
// C++
#include <iostream>
extern "C" void function_in_cpp() {
std::cout << "Greetings from C++\n";
}
// C
void function_in_cpp(void);
void function_in_c(void) {
function_in_cpp();
}
You cannot. You can use C functions in your C++ program. But you cannot use C++ stuff from C. When C++ was invented, it allowed for compatibility and reuse of C functions, so it was written as a superset of C, allowing C++ to call all the C library functions.
But the reverse is not true. When C was invented, there was no C++ language defined.
The only way you can call C++ functions is to convert your whole project into a C++ one... you need to compile your C functions with a C++ compiler (or a C compiler if they are plain C) but for a C function to call a C++ function it must be compiled as C++. You should declare it with:
extern "C" {
void my_glue_func(type1 param1, type2 param2, ...)
{
/* ... */
}
} /* extern "C" */
and link the whole thing as a C++ program (calling the c++ linker)
This is because C doesn't know anything about function overloading, class initializacion, instance constructor calls, etc. So if you even can demangle the names of the C++ functions to be able to call them from C (you had better not to try this), they will probably run uninitialized, so your program may (most) probably crash.
If your main() function happens to be a C function, then there's no problem. C++ was designed with this thing in mind, and so, main() is declared implicitly as extern "C". :)
My C++ program needs to use an external C library.
Therefore, I'm using the
extern "C"
{
#include <library_header.h>
}
syntax for every module I need to use.
It worked fine until now.
A module is using the this name for some variables in one of its header file.
The C library itself is compiling fine because, from what I know, this has never been a keyword in C.
But despite my usage of the extern "C" syntax,
I'm getting errors from my C++ program when I include that header file.
If I rename every this in that C library header file with something like _this,
everything seems to work fine.
The question is:
Shouldn't the extern "C" syntax be enough for backward compatibility,
at least at syntax level, for an header file?
Is this an issue with the compiler?
Shouldn't the extern "C" syntax be enough for backward compatibility, at least at syntax level, for an header file? Is this an issue with the compiler?
No. Extern "C" is for linking - specifically the policy used for generated symbol names ("name mangling") and the calling convention (what assembly will be generated to call an API and stack parameter values) - not compilation.
The problem you have is not limited to the this keyword. In our current code base, we are porting some code to C++ and we have constructs like these:
struct Something {
char *value;
char class[20]; // <-- bad bad code!
};
This works fine in C code, but (like you) we are forced to rename to be able to compile as C++.
Strangely enough, many compilers don't forcibly disallow keyword redefinition through the preprocessor:
#include <iostream>
// temporary redefinition to compile code abusing the "this" keyword
#define cppThis this
#define this thisFunction
int this() {
return 1020;
}
int that() {
return this();
}
// put the C++ definition back so you can use it
#undef this
#define this cppThis
struct DumpThat {
int dump() {
std::cout << that();
}
DumpThat() {
this->dump();
}
};
int main ()
{
DumpThat dt;
}
So if you're up against a wall, that could let you compile a file written to C assumptions that you cannot change.
It will not--however--allow you to get a linker name of "this". There might be linkers that let you do some kind of remapping of names to help avoid collisions. A side-effect of that might be they allow you to say thisFunction -> this, and not have a problem with the right hand side of the mapping being a keyword.
In any case...the better answer if you can change it is...change it!
If extern "C" allowed you to use C++ keywords as symbols, the compiler would have to resolve them somehow outside of the extern "C" sections. For example:
extern "C" {
int * this; //global variable
typedef int class;
}
int MyClass::MyFunction() { return *this; } //what does this mean?
//MyClass could have a cast operator
class MyOtherClass; //forward declaration or a typedef'ed int?
Could you be more explicit about "using the this name for some variables in one of its header files"?
Is it really a variable or is it a parameter in a function prototype?
If it is the latter, you don't have a real problem because C (and C++) prototypes identify parameters by position (and type) and the names are optional. You could have a different version of the prototype, eg:
#ifdef __cplusplus
extern "C" {
void aFunc(int);
}
#else
void aFunc(int this);
#endif
Remember there is nothing magic about header files - they just provide code which is lexically included in at the point of #include - as if you copied and pasted them in.
So you can have your own copy of a library header which does tricks like the above, just becoming a maintenance issue to ensure you track what happens in the original header. If this was likely to become an issue, add a script as a build step which runs a diff against the original and ensures the only point of difference is your workaround code.
Suppose I have the following code, is something like that possible to do?
I mean passing a variable that is inside a c++ object to a function.
In foo.hpp
class foo
{
public :
int a;
}
in main.cpp
#include "cfile.h"
#include "foo.hpp"
void main()
{
foo * fooPtr = new foo();
int RetVal = MyCfunc(fooPtr->a);
}
In cfile.c
#include "cfile.h"
int MyCfunc(int var)
{
var + = 1;
return var;
}
Technically this compiles (well, after fixing various syntactic issues that have been pointed out already), but you have to be careful. You need to make sure everything can link (i.e. symbols are created correctly for both, C and C++ source code); I usually use g++ as a compiler which, for C files, works fine. Second, you have to make sure to tell your C++ code that you want to reference C code. Therefore, in your "cfile.h" you want to add
#ifdef __clpusplus
extern "C" {
#endif
// your C include file
#ifdef __cpluspus
}
#endif
That ensures that you can include your C include file into C++ sources, while telling the C++ compiler to use C style name mangling when compiling the code. Then go ahead and compile with C and C++ files, and link them into an executable:
g++ -g -O0 -o test main.cpp cfile.c
There is more about this here: Combining C++ and C - how does #ifdef __cplusplus work?
It would be better if you supplied an actual sample of what you're trying to do. As other have pointed out, the code you supplied has a number of syntax problems and passing basic types between C & C++ is mostly never a problem. An int is an int everywhere (as long as you aren't crossing 32/64 bit boundaries).
Where you can get into trouble is calling C/C++ functions/methods from the other side or passing classes around (use pointers and only pass them, usually, when in C code).
This question already has answers here:
How to call C++ function from C?
(7 answers)
Closed 5 years ago.
I have a header declaring functions that take pointers to C++ objects as parameters. The implementaton is in a seperate C++ file. How can I include this header in C and use the functions in C even though the arguments need to be C++ object pointers?
Unfortunately, my first attempt answered the wrong question....
For the question you did ask...
You can, as someone point out, pass around void *'s. And that's what I would also recommend. As far as C is concerned, pointers to C++ objects should be totally opaque.
C++ functions can be labeled extern "C" as well if they are in the global namespace. Here is an example:
myfunc.hpp:
#ifdef __cplusplus
extern "C" {
#endif
extern int myfunction(int, void *ob);
#ifdef __cplusplus
}
#endif
myfunc.cpp:
#include "myfunc.hpp"
void myfunction(int x, void *vobptr)
{
ClassType *ob = static_cast<ClassType *>(vobptr);
}
afoofile.c
#include "myfunc.hpp"
void frobble(int x, void *opaque_classtype_ptr) {
myfunction(x, opaque_classtype_ptr);
/* do stuff with buf */
}
The other option is to do basically the same thing with creative use of typedefs in C. This, IMHO, is quite ugly, but here is an example anyway:
myfunc.hpp:
#ifdef __cplusplus
extern "C" {
#else
typedef void ClassType; /* This is incredibly ugly. */
#endif
extern int myfunction(int, ClassType *ob);
#ifdef __cplusplus
}
#endif
myfunc.cpp:
#include "myfunc.hpp"
void myfunction(int x, ClassType *ob)
{
// Do stuff with ob
}
afoofile.c
#include "myfunc.hpp"
void frobble(int x, ClassType *opaque_classtype_ptr) {
myfunction(x, opaque_classtype_ptr);
/* do stuff with buf */
}
If your C code just needs to pass the pointers around, and eventually pass it back to some C++ that'll actually deal with the object it points to, you should be able to use a void * in the C code, and cast back to T * when it goes back into C++.
If you plan on the C code actually using the pointer, you're pretty much stuck with reverse engineering what your compiler happens to do, and trying to emulate it closely enough to make things work. Even at best, this is going to be ugly and fragile.
Make a wrapper module that's C++ but whose external functions are declared extern "C". This will allow you to access C++ code cleanly from C. Naturally the wrapper should replace any pointers to types not representable in C (i.e. classes) with either void pointers (the quick and dirty solution) or pointers to incomplete struct types (which would provide some level of type-safety as long as they're used consistently.
The secret is "extern C", whose primary purpose is the prevention of name decoration.
You can't. You'll have to create a C-compatible abstraction layer:
typedef struct foowrapper *foohandle;
foohandle foo_create();
void foo_delete(foohandle);
int foo_getvalue(foohandle);
void foo_dosomething(foohandle, const char* str);
Leaving this as after reading allsorts of posts on this topic, this was the easiest to follow.
http://research.engineering.wustl.edu/~beardj/Mixed_C_C++.html
Also, in netbeans the example ran out of the box without having to touch the makefile.
Check out this link:-
http://developers.sun.com/solaris/articles/mixing.html
The link contains the following topics:
Using Compatible Compilers
Accessing C Code From Within C++ Source
- Accessing C++ Code From Within C Source
Mixing IOstream and C Standard I/O
Working with Pointers to Functions
Working with C++ Exceptions
Linking the Program
I have to import/translate the code from one C++ class so that I may use it in a C program.
The C program is large and has lots of dependencies on C libraries both open and closed.
The C++ Class .cpp file is 650 lines
I have no experience mixing C and C++ so even though I have looked at one guide on how to do it, I am not convinced which way to go.
I only have to use the C++ code in a few spots (fairly isolated useage
I am using gcc (gcc/g++)
It is a linux environment
So what do I have to do to import it? and will it be less time than translating?
Thanks,
Mike
Hmm, 650 lines is not too long - I'd re-write it. You will probably spend at least as much time trying to wrap it, and you may find maintaining the result difficult.
This might be useful: http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html
You need to create functions in C++ that are 'extern "C"', so they are callable from C.
You can get OO by making the this pointer explicit (and of type void *), with the implementation casting the pointer and forwarding to the real member function.
In your C++ code, you must use the extern "C" construct to instruct the compiler/linker to generate compatible linkage so that the C code can call your C++ code.
extern "C"
{
void my_function_that_can_be_called_from_c()
{
// ...
}
}
C code doesn't know anything about objects, so you can't easily use C++ objects from C. A common technique is to manipulate C++ objects inside the "externed" function.
Say you have the following C++ class:
#if __cplusplus // only C++ programs see this part of foo.h
class foo {
public:
// a couple constructors
foo();
foo( int);
// and a couple methods
bool dosomething();
bool doSomethingElse( std::string const&);
private:
// a bunch of private stuff which is immaterial to the C interface
}
#endif
What you can do is have a set of C-callable functions that wrap the C++ interface:
// both C and C++ programs can see this part of foo.h
#if __cplusplus // but C++ programs need to know that no name mangling should occur
extern "C" {
#endif
struct CFoo_struct;
typedef struct CFoo_struct foo_t; // used as a handle to a foo class pointer
// constructors
foo_t* CreateFoo( void);
foo_t* CreateFoo_int( int);
int CFooDoSomething( foo_t*);
int CFooDoSomethingElse( foo_t*, char const*);
#if __cplusplus
} // end the extern "C" block
#endif
Then the implementation in foo.cpp might look something like:
// in foo.cpp
extern "C" {
struct CFoo_struct {
};
// constructors
foo_t* CreateFoo( void)
{
foo* pFoo = new Foo;
// a bit of ugliness - the need for this cast could be
// avoided with some overhead by having the foo_t
// struct contain a foo* pointer, and putting a foo_t
// structure inside the foo class initialized with
// the this pointer.
return reinterpret_cast<foo_t*>( pFoo);
}
// something similar for CreateFoo_int()...
// method wrappers
int CFooDoSomethingElse( foo_t* pHandle, char const* s)
{
foo* pFoo = reinterpret_cast<foo*>( pHandle);
std::string str( s);
return pFoo->doSomethingElse( str);
}
// something similar for CFooDoSomething()
} // end extern "C" block
If you want to turn the C++ class into a Linux shared library accessible to your C programs, this answer to a previous question shows you how with a small example class.
There's various things you can do.
You can rewrite it in C. Without actually seeing the code, I don't know how much trouble that would be. Much C++ code is simply C with a few addons, and some makes heavy use of templates and overloaded functions and such.
If you're not doing this, you need to make it communicate well with C. This means providing an interface for C, and surrounding it with extern "C"{ ... } so the C++ compiler will know to make the interface C-compatible. Again, without knowing something of the C++ code, I can't tell how much work this would be. You'll need the wrapper for either of the following solutions.
You can make this a C++ project, surround every C file with extern"C" { ... }, and just link it in. If you have any C++ files, the whole compilation has to be C++.
You can make a separate library to be linked in.
What you can't do is compile C and C++ together with a C main() function, or with a C compiler. C++ is more demanding, and requires more from the main() function.
You could always try recompiling the C files you're using as C++, and wrapping the .h files for the libraries in extern "C" { ... }. Well-written C90 isn't that far from being legal C++ (although the C99 standard moved away from that some), and the compiler will flag any conversion problems you find.
Which of these is the best idea for you depends on questions like:
How easy is the C++ code to convert?
How easy is it to write a C wrapper for the C++ functionality you want?
How many changes are you willing to make to the C code?
How familiar are you with making a Linux library?