I'm working with a contractor who develops a library for us in C++. I would like to know if it is possible to use that library in a C program. I am using Gcc as my compiler.
4 Answers
Yes, it is possible. However, as BoBTFish says in a comment above, you (or the contractor) must design a C interface for the C++ library:
- write a header file that compiles in both C and C++, and that declares some
extern "C"functions. The interfaces of these functions must be valid in C, which in C++ terms means they use only POD types (for example no references) and don't throw exceptions. You can declare non-POD C++ classes as incomplete types and use pointers to them, so commonly each non-static member function is wrapped by a function that takes the pointer that will becomethisas its first parameter. - implement the functions in C++ to call the C++ library
- compile the library and the wrapper as C++
- compile your program as C (you can
#includethe header wherever needed) - link it all together with g++ so that the C++ components can link against libstdc++.
I suppose you might argue that since the program is linked with g++, it's by definition a C++ program that uses a C library (that happens to contain main) rather than a C program that uses a C++ library. Personally I wouldn't bother arguing that, the important point is that none of your existing C code changes.
Example:
lib.h
#ifdef __cplusplus extern "C" #endif int foo(); lib.cpp
#include "lib.h" #include <vector> #include <iostream> int foo() { try { std::vector<int> v; v.push_back(1); v.push_back(1); std::cout << "C++ seems to exist\n"; return v.size(); } catch (...) { return -1; } } main.c
#include "lib.h" #include <stdio.h> int main() { printf("%d\n", foo()); } build
g++ lib.cpp -c -olib.o gcc main.c -c -omain.o g++ main.o lib.o -omain The following also works instead of the third line, if you do want to make an arbitrary distinction between using gcc to link and using g++:
gcc main.o lib.o -llibstdc++ -omain However, I am not certain that gcc -libstdc++ will work as well as g++ for all possible code that could be in lib.cpp. I just tested it for this example, and of course there's a lot of C++ that I haven't used.
11 Comments
gcc but some nomenclature of their own) to link a C++ library into a program written in C. You've invented an artificial restriction. g++ is part of GCC.gcc command-line that works for my example code. But since the restriction is arbitrary and has nothing to do with the question, I'm not going to research whether it always works or whether there are any cases that need more than just -llibstdc++. The man page for g++ is the same as the man page for gcc, and it says that gcc is the GNU C and C++ compiler. I don't know who told you otherwise, or what situation you have in mind where it makes sense to avoid g++.main to be compiled as C++ if there is any C++ code anywhere in the program. I cannot remember whether GCC requires this on any current OS.This little dynamic library (g++) and program (gcc) compiles and links perfectly:
Header library.h
#ifdef __cplusplus extern "C" { #endif typedef struct TagPerson {} Person; extern Person* person_create(const char* name); extern void person_destroy(Person* p); extern const char* person_name(Person* p); extern Person* person_exception(Person* p); #ifdef __cplusplus } #endif C++ Source library.cc compiled with g++ -shared -fpic library.cc -o libLibrary.so
#include <iostream> #include <string> #include <stdexcept> #include "library.h" namespace Library { class Person { public: Person(const std::string& name) : m_name(name) { std::cout << m_name << std::endl; } const std::string name() const { return m_name; } void exception() { throw std::runtime_error(""); } private: std::string m_name; }; } // namespace N extern "C" { #define PERSON(P) ((Library::Person*)(P)) extern Person* person_create(const char* name) { try { return (Person*)(new Library::Person(name)); } catch(...) { // Error Procession; } return 0; } extern void person_destroy(Person* p) { delete PERSON(p); } extern const char* person_name(Person* p) { return PERSON(p)->name().c_str(); } extern Person* person_exception(Person* p) { try { PERSON(p)->exception(); } catch(...) { std::cerr << "Exception" << std::endl; } return 0; } } // extern "C" C Source main.c compiled with gcc main.c -lLibrary -o Test
#include <stdio.h> #include "library.h" int main() { Person* p = person_create("Jaco Pastorius"); printf("%s\n", person_name(p)); person_exception(p); person_destroy(p); return 0; } 2 Comments
No, it is not possible. One thing that is certanly going to miss are exception handling functions. You have to compile the main using c++ compiler.
If you really want to develop in c, and use a c++ library, you can develop a c library, and compile main with g++.
Even if compiling succeeds, linking will fail at the end. See : Why can't I link a mixed C/C++ static library that has a C interface using gcc?
And it is not only exception functionality missing. There are lots of other things, which can be easily solved by using g++ to link everything.
As I said above, the solution is to call some function from main and link it with g++ :
#include "my_c_main.h" int main(int argc, char* argv[]) { return run_my_c_main( argc, argv ); } 8 Comments
-lstdc++, but i wouldn't be so quick with 'not possible' claims (i use it and it works). Although not actually remember, exceptions and RTTI are likely to be disabled in my builds. After all, a lot of libraries are written in C++ but expose interface to external programs via C functions.gcc to link my C code with ODE and squirrel - both C++ libraries with extern "C" interface. And adding -lstdc++ is enough for me - both with GNU toolchain and with xmingw.What exactly is the issue? Do you already have a delivered library in the "wrong" language or is it that your contractor wants to develop the library in C++ but you need it to link from C?
In the former case, assuming you specified things correctly you should make it your contractor's problem but if you didn't or if that's not possible you'll need to write an interface as Steve Jessop suggests above.
In the latter case, it's really not an issue: the contractor will need to ensure that she provides the code in a form that is callable from C and safe/secure/stable to call in that manner. The internal code that does the work can really be anything at all providing she wraps it up for you in the correct manner. If you're planning on building the library yourself, you will need them to provide suitable build scripts that invoke the compiler in the right manner. I guess there's a potential maintenance issue if your in-house programmers can't cope with C++ but that's an issue to do with recruitment/employment not the technical details of how it works.
C++that exposes aCinterface usingextern "C". So no, not directly, but yes, it is possible, in some limited way.extern "C"?