Can I use shared library created in C++ in a C program?

前端 未结 3 1686
情话喂你
情话喂你 2020-12-04 08:26

I am creating programs using C. However, I require to use a lot of libraries that have API\'s only for C++. So, is it possible that I can create a shared object in C++ and t

3条回答
  •  我在风中等你
    2020-12-04 09:31

    You want something more like this (and here I will use a slightly more meaningful example):

    C/C++ header - animal.h

    #ifndef ANIMAL_H
    #define ANIMAL_H
    
    #ifdef __cplusplus
    class Animal {
    public:
        Animal() : age(0), height(0) {}
        Animal(int age, float height) : age(age), height(height) {}
        virtual ~Animal() {}
    
        int   getAge();
        void  setAge(int new_age);
    
        float getHeight();
        void  setHeight(float new_height);
    
    private:
        int age;
        float height; // in metres!
    };
    #endif /* __cplusplus */
    
    #ifdef __cplusplus
    extern "C" {
    #endif
        struct animal; // a nice opaque type
    
        struct animal *animal_create();
        struct animal *animal_create_init(int age, float height);
        void           animal_destroy(struct animal *a);
    
        void           animal_setage(struct animal *a, int new_age);
        void           animal_setheight(struct animal *a, float new_height);
        int            animal_getage(struct animal *a);
        float          animal_getheight(struct animal *a);
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* ANIMAL_H */
    

    C++ animal implementation file - animal.cpp

    #include "animal.h"
    #define TO_CPP(a) (reinterpret_cast(a))
    #define TO_C(a)   (reinterpret_cast(a))
    
    void  Animal::setAge(int new_age) { this->age = new_age; }
    int   Animal::getAge() { return this->age; }
    void  Animal::setHeight(float new_height) { this->height = new_height; }
    float Animal::getHeight() { return this->height; }
    
    animal *animal_create() {
        animal *a = TO_C(new Animal);
        return a;
    }
    
    animal *animal_create_init(int age, float height) {
        animal *a = TO_C(new Animal(age, height));
        return a;
    }
    
    void animal_destroy(animal *a) {
        delete TO_CPP(a);
    }
    
    void animal_setage(animal *a, int new_age) {
        TO_CPP(a)->setAge(new_age);
    }
    
    void animal_setheight(animal *a, float new_height) {
        TO_CPP(a)->setHeight(new_height);
    }
    
    int animal_getage(animal *a) {
        TO_CPP(a)->getAge();
    }
    
    float animal_getheight(animal *a) {
        TO_CPP(a)->getHeight();
    }
    

    C client code - main.c

    #include "animal.h"
    #include 
    
    int main()
    {
        // 6'0" 25yo (perhaps a human? :P)
        struct animal *a = animal_create(25, 1.83); 
    
        animal_setage(a, 26); // birthday
        printf("Age: %d\nHeight: %f", animal_getage(a), animal_getheight(a));
    
        animal_destroy(a);
        return 0;
    }
    

    C++ client code - main.cpp

    #include "animal.h"
    #include 
    
    int main()
    {
        // 6'0" 25yo (perhaps a human? :P)
        Animal* a = new Animal(25, 1.83);
        a->setAge(26); // birthday
        std::cout << "Age:    " << a->getAge() << std::endl;
        std::cout << "Height: " << a->getHeight();
    
        delete a;
        return 0;
    }
    

    So when you compile the library, you compile animal.cpp with a C++ compiler. You can then link to it with C code, and use the animal_xxx functions.

    Note the use of struct animal and Animal. Animal is a normal C++ type. It's exactly what it looks like. struct animal, on the other hand, is an "opaque" type. That means that your C program can see it's there, and can have one, but it doesn't know what is inside it. All it knows is that it has a function that takes a struct animal*.

    In a real library you will want to have customisation points for memory allocation. So assuming this is the library libjungle, you probably want at least jungle_setmalloc and jungle_setfree with sensible defaults. You can then set up the global new and delete in libjungle's C++ code to use these user-defined functions.

提交回复
热议问题