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.
Related
I have c++ library .so. My co-worker is working on c program which will call c++ library from his c program. I told him to create Wrapper.h and Wrapper.cpp and use pointer for passing around c++ objects in his c program. However, I found that he was trying to modify our c++ library source code by adding Wrapper.cpp and header into our library .so directly. For example:
class A{ SetValueA(int); }
class B{ SetValueB(int); }
In his Wrapper.cpp, he wrote sth like this:
A a;
B b;
extern "C" SetValueA(int) {a.SetValueA(int); }
extern "C" SetValueB(int) {b.SetValueB(int); }
Then he recompiled our c++ library and includes Wrapper.h in his c program.
What I told him is to do sth like this:
In my Wrapper.cpp
extern "C" {
A* newClassA() {
return new A();
}
void SetValueA(A* v, int i) {
v->SetA(i);
}
B* newClassB() {
return new B();
}
void SetValueB(B* v, int i) {
v->SetB(i);
}
void deleteClassA(A* v) {
delete v;
}
void deleteClassB(B* v) {
delete v;
} }
Then I just compiled my Wrapper.cpp and linked with our c++ library. In his c program, he just need to include Wrapper.h and compile his c code, and then compile Wrapper.o and main.o(from main.c) by using c++ compiler.
His solution looks working too, he complained that the way I told him is more works. But I dont want him to change our c++ library coz nobody else will use Wrapper class from c++ library. Can you tell me which one is the better and why?
Yes, I also dont like his way using global variable in his wrapper.
I don't see why there is a need to change any library file to use global variables: the necessary change should b confined to Wrapper.cpp which is clearly part of the wrapper.
That said, I don't believe in the use of any [mutable] global object. They tend to be a problem in many different ways. That is, I'd agree that the proper approach to create a wrapper is to effectively deal with the necessary life-time management. I do realize that getting life-time management properly sorted in C is harder than in C++. The fix to that is to use C++, not to create unnecessary dependencies (I'm aware that this argument typically doesn't fly with C programmers).
The wrapper that your co-worker wrote is of course indiscutable due to the use of global variables, which introduce many issues into your library.
However, I believe, a well written library should export a C interface by itself, even if it uses C++ internally. For the simple reason that a C interface can be imported into virtually every language, while a C++ interface requires user code to be C++. Also, forcing this kind of wrapper into user code is likely to lead to a proliferation of different wrapper.cpp versions, all of which are incomplete and out of date in different ways.
As such, I would include code along the lines of your wrapper.cpp into your library. And I would certainly move it close to the code that it wraps, instead of bundling it all in one big, fat wrapper.cpp. That way it is much easier to check whether all your public methods have been wrapped properly.
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.
Hoi,
I have a dynamic library loader, which is written in C++ but provides a C-compatible API.
That loader can load modules, which are written in any programming language. They're arranged in a named list and can request function pointers of other modules. Now, a module written in C and compiled with a C compiler gets the functions pointers of any other module, which is written and compiled in C++.
So my question: Are function-pointers cross-compiler valid? I think I heard of something like __cdecl once, long time ago. I use Linux 64bit.
T.I.A.
// my C++ code ...
extern "C" {
void thisFunctionWillBeCallableFromC();
}
void butThisOneMayNot();
struct S
{
void thisDefinitelyWontBeCallableFromC(std::map<int, S>);
};
C++ code should declare interfaces with extern "C" linkage to be callable from C.
Or do you mean C++ code generated by different compilers?
Function pointers are compatible between C and C++.
The only limitation, is that you have to declare your C-functions with extern "C" linkage when used within C++:
extern "C"
{
int foo();
}
I'd like to use Pure Data as a prototyping tool for my own library. I found out that Pure Data patches are written in C, but my library is written in C++. So how can I use this code in pure data? Since I haven't used plain C, I'd like to know how I could write a C wrapper for C++ classes and how do instantiate my classes then? Or do I have to rewrite everything in C?
You will need to write wrapper functions for every function which needs to be called. For example:
// The C++ implementation
class SomeObj { void func(int); };
extern "C" {
SomeObj* newSomeObj() {return new SomeObj();}
void freeSomeObj(SomeObj* obj) {delete obj;}
void SomeObj_func(SomeObj* obj, int param) {obj->func(param)}
}
// The C interface
typedef struct SomeObjHandle SomeObj;
SomeObj* newSomeObj();
void freeSomeObj(SomeObj* obj);
void SomeObj_func(SomeObj* obj, int param);
Note this must be C++ code. The extern "C" specifies that the function uses the C naming conventions.
You can also write objects for Pure Data using C++ using the flext framework.
Let me put it another way:
1) You can call C functions, data and libraries from C++ source, and you call C++ source from C.
2) Whenever C calls into C++ source, however, that source must be written in a C subset of C++.
3) Part of this is using "extern C".
4) Another part is using "#ifdef __cplusplus"
5) The links I cited above give plenty of details
6) I looked at the Pure Data site. You might have to make some "tweaks" to your library. You might wish to create a new header. But fundamentally, I think you can probably accomplish your goal of getting your library to integrate with Pure Data.
IMHO...
You can absolutely call C from C++ - no problemo!
Worst case, you might have to explicitly declare those functions you call from Pure Data as "extern C". But it's almost certain that Pure Data has already done that for you (you'll probably see "extern C" in the Pure Data header files.
Here's more info:
http://msdn.microsoft.com/en-us/library/0603949d%28v=vs.80%29.aspx
'Hope that helps!
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.