How to mix C++ and C correctly

前端 未结 2 1141
忘掉有多难
忘掉有多难 2020-11-27 22:16

I am having some problems with this: I need to write a C wrapper for a C++ library. Say I have 3 files:

  • wrapper.h

    typedef struct Foo Foo;
    Fo         
    
    
            
相关标签:
2条回答
  • 2020-11-27 22:34

    You are creating a shared object named a.out, then another shared object named libbindings.so that ostensibly links to a.out but references nothing from it. Now if a set of input files doesn't have any undefined symbols, no libraries are searched or added to the output. So libbindings.so is essentially an empty library. Verify:

     % nm a.out | grep create_foo
     00000000000006bc T create_foo
     % nm libbindings.so | grep create_foo
     %
    

    If you have several source files, you should build an object file from each source (use -c compilation flag), (then optionally combine the objects into a static library --- skip this step if you are not releasing static libraries) then build a shared object from previously built objects:

      clang++ -c -fPIC foo.cpp
      clang++ -c -fPIC bar.cpp
      clang++ -shared -o libfoobar.so foo.o bar.o
    

    If you only have one source, or very few source files you can easily compile together, you can build the shared library in one step:

      clang++ -std=c++14 wrapper.cpp somethingelse.cpp -shared -fPIC -o libbindings.so
    

    This is not recommended for large projects.

    0 讨论(0)
  • 2020-11-27 22:50

    Here is a working example:

    wrapper.h (C & C++ aware)

    #ifndef WRAPPER_H_
    #define WRAPPER_H_
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    typedef struct CPPClass CPPClass;
    
    CPPClass* CPPClass_new();
    void CPPClass_do_something(CPPClass* cppclass);
    int CPPClass_get_state(CPPClass* cppclass);
    void CPPClass_delete(CPPClass* cppclass);
    
    #ifdef __cplusplus
    }
    #endif
    #endif /* WRAPPER_H_ */
    

    wrapper.cpp (C++ only)

    #include "wrapper.h"
    
    class CPPClass
    {
        int state;
    public:
        CPPClass(): state(0) {}
        void do_something() { ++state; }
        int get_state() const { return state; }
    };
    
    extern "C" CPPClass* CPPClass_new()
    {
        return new CPPClass;
    }
    
    extern "C" void CPPClass_do_something(CPPClass* cppclass)
    {
        cppclass->do_something();
    }
    
    extern "C" int CPPClass_get_state(CPPClass* cppclass)
    {
        return cppclass->get_state();
    }
    
    extern "C" void CPPClass_delete(CPPClass* cppclass)
    {
        delete cppclass;
    }
    

    use-wrapper.c (C only)

    #include <stdio.h>
    #include "wrapper.h"
    
    int main(void)
    {
        CPPClass* cppclass = CPPClass_new();
    
        if(!cppclass)
        {
            printf("ERROR: failed to create CPPClass:\n");
            return 1;
        }
    
        printf("state: %d\n", CPPClass_get_state(cppclass));
        CPPClass_do_something(cppclass);
        printf("state: %d\n", CPPClass_get_state(cppclass));
    
        CPPClass_delete(cppclass);
    }
    

    Compile CPP

    g++ -std=c++11 -shared -fPIC -o libwrapper.so wrapper.cpp
    

    Compile C

    gcc -o use-wrapper use-wrapper.c -L. -lwrapper -lstdc++
    

    Output:

    $ ./use-wrapper 
    state: 0
    state: 1
    

    Hope that helps.

    0 讨论(0)
提交回复
热议问题