7

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.

Lokesh A. R.
  • 2,326
  • 1
  • 24
  • 28
hephaestuz
  • 123
  • 1
  • 5
  • 9
    You need to write some wrapper in `C++` that exposes a `C` interface using `extern "C"`. So no, not directly, but yes, it is possible, in some limited way. – BoBTFish Dec 02 '13 at 09:32
  • 3
    @BoBTFish that + compiling main with g++ – BЈовић Dec 02 '13 at 09:36
  • @BЈовић what, why? Why would that be necessary if you're just linking to another library which exposes an interface declared with `extern "C"`? – jalf Dec 02 '13 at 09:37
  • @jalf For example this : http://stackoverflow.com/a/329195/476681 – BЈовић Dec 02 '13 at 09:44
  • 3
    Alternatively, upgrade to C++ as your main language. Most C code will work just fine, and the world will be a better place. – RichardPlunkett Dec 02 '13 at 09:46
  • @jalf See also this : http://stackoverflow.com/q/7397302/476681 – BЈовић Dec 02 '13 at 09:48
  • 1
    @BЈовић yes, it is obviously problematic to *compile* C++ object files into a C program. But you can link to a (dynamic) C++ library just fine, provided it exposes a C interface – jalf Dec 02 '13 at 11:29

4 Answers4

25

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 become this as 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 #include the 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.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • 1
    -1, since it is not possible to link a c++ library using gcc, and you said it is possible to do it. I change my mind if you prove it wrong. – BЈовић Dec 02 '13 at 10:24
  • @BЈовић: what would you accept as proof? Note that I specified using `g++` to link, which is part of GCC but is not identical in behavior to calling the `gcc` program. I don't remember what argument(s) `gcc` needs in order to make it behave the same as `g++`. IIRC it's the same program but it checks its own `argv[0]`, so it might be there is no set of arguments that makes it *exactly* the same. – Steve Jessop Dec 02 '13 at 10:32
  • The question is how to link a c++ library using gcc. Your answer tells it is possible, and then you want to use g++. I'd like to see how exactly can I link a c++ library using gcc (and not g++). – BЈовић Dec 02 '13 at 10:40
  • 3
    @BЈовић: no, the question is how to use GCC (well, the questioner specifically says "Gcc", so I guess that's neither GCC nor `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. – Steve Jessop Dec 02 '13 at 10:41
  • gcc and g++ are different programs. The first is for C, and the second for C++. You know it, so I am not really sure what is not clear. If somebody says they use gcc, I do not assume one of GCC tools. Again, your edit uses g++ to link both libraries (c and c++). So, I'd like to see how it is possible to link a c++ library using gcc. You, BoBTFish, keltar and apparently more people know how, since you said it is possible. – BЈовић Dec 02 '13 at 10:50
  • 4
    @BЈовић: I've now included a `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++`. – Steve Jessop Dec 02 '13 at 10:57
  • Oh, I suppose there's the special case where C++ doesn't work on the target platform at all. In that case step 1 and step 3 of my "build script" are both problematic. Clearly you can't use C++ code in a C program (or for that matter in any program) if you don't have a working C++ compiler. If that's the restriction that the questioner is trying to state then it's game over. The library needs to be in a language the target supports, so either rewrite it or else get a C++ compiler working for the target and try again :-) – Steve Jessop Dec 02 '13 at 14:37
  • 1
    The last thing: c and c++ are different languages. That means that gcc and g++ have to follow different rules. I am not against g++, but some times it is not possible to switch from gcc to g++ (big project,or some other weird reason). – BЈовић Dec 03 '13 at 07:22
  • @BЈовић: I don't think they follow different rules at link time (the names have been mangled differently, but that happens earlier). `extern "C"` was specifically designed to (a) let you write a header in C++ to bind against a C library, which is the more common use but also (b) let you write, in C++, a library that behaves exactly as a C library. – Steve Jessop Dec 03 '13 at 08:02
  • @SteveJessop On ELF systems, there is no meaningful difference between the `ld` invocation generated by using `g++` to link, and the `ld` invocation generated by using `gcc` to link, as long as `-lstdc++` is placed after all object files in the latter case. There may be a meaningful difference on OSes that use less featureful object file formats. – zwol Dec 08 '13 at 22:36
  • 1
    @SteveJessop Worth pointing out in this context, the language in the C++ standard about mixed C and C++ permits (but does not require) an implementation to require `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. – zwol Dec 08 '13 at 22:39
0

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;
}
  • I must say I am not sure how that works. However, you have an UB. C standard specify that the program execution starts in main, but your program starts before by the initialization of global objects (which you included with iostream). – BЈовић Dec 02 '13 at 18:27
  • @BЈовић Please notice, it is an dynamic library hiding the c++ part. –  Dec 02 '13 at 18:43
-1

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 );
}
Community
  • 1
  • 1
BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • Well, it would require something like `-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. – keltar Dec 02 '13 at 10:01
  • @keltar Feel free to add an answer, as I'd really like to see how exactly you did it. As far as I know, without using g++, it is not possible to link c++ libraries. – BЈовић Dec 02 '13 at 10:35
  • 1
    @SteveJessop I am not. The question is about gcc - not g++. I said OP needs to use g++ if he wants to link c++ libraries. There are no ways around it. – BЈовић Dec 02 '13 at 10:51
  • It's entirely possible, it just takes effort. – Jack Aidley Dec 02 '13 at 10:53
  • @BЈовић second answer already states that, no need to add more. But yes, i use `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. – keltar Dec 02 '13 at 10:55
  • @BЈовић the OP said nothing about wanting to use a *static* library, did he? If you make up enough additional requirements, then *anything* can become impossible. – jalf Dec 02 '13 at 11:30
  • @jalf static or dynamic c++ library - doesn't matter. Did you ask because I linked a question where they tried to link static c++ library? – BЈовић Dec 02 '13 at 12:09
  • @BЈовић I ask because it *does* matter, and because your answer is incorrect. – jalf Dec 02 '13 at 12:12
-1

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.

Jack Aidley
  • 19,439
  • 7
  • 43
  • 70