programing

C 프로그램에서 C++로 만든 공유 라이브러리를 사용할 수 있습니까?

cafebook 2023. 7. 22. 10:25
반응형

C 프로그램에서 C++로 만든 공유 라이브러리를 사용할 수 있습니까?

저는 C를 이용하여 프로그램을 만들고 있습니다.하지만 저는 C++ 전용 API가 있는 라이브러리를 많이 사용해야 합니다.그렇다면 C++에서 공유 객체를 생성한 다음 C를 사용하여 해당 기능에 액세스할 수 있습니까?

  1. 제가 전달하고 반환할 데이터는 C 호환 데이터 유형뿐입니다.
  2. 여기서는 cpp로 변환하거나 마이그레이션하는 것이 옵션이 아닙니다.

이러한 코드를 인터페이스할 수 없는 경우 C++ 코드에서 C 코드로 정보를 가져오려면 어떻게 해야 합니까?C에서 C++ 함수를 호출하려고 했는데 링크 중에 오류가 발생합니다.<string>그럼 C에서 C++ 함수를 호출할 때 C 컴파일러와 호환되는 코드만 사용해야 합니까?

C++ 헤더 cppfile.hpp

#ifndef CPPFILE_H
#define CPPFILE_H
    #ifdef __cplusplus
    extern "C" {
    #endif

    extern int myfunction(const char *filename);

   #ifdef __cplusplus
   }
   #endif
#endif

C++ 파일 cppfile.cpp

#include "cppfile.hpp"
#include <string>
int myfunction(const char *filename) {
    String S(filename);
    return 0;
}

C 파일 cmain.c

#include "cppfile.hpp"
int main(int argc, char **argv)
{
     int i = myfunction(argv[1]);
     printf("%d\n", i);
     return 0;
}

컴파일 중:

gcc -c cmain.c
g++ -fPIC -shared -o cppfile.so cppfile.cpp

당신은 다음과 같은 것을 더 원할 것입니다(여기서는 조금 더 의미 있는 예를 사용하겠습니다).

C/C++ 헤더 - 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.cpp

#include "animal.h"
#define TO_CPP(a) (reinterpret_cast<Animal*>(a))
#define TO_C(a)   (reinterpret_cast<animal*>(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 클라이언트 코드 - main.c

#include "animal.h"
#include <stdio.h>

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++ 클라이언트 코드 - main.cpp

#include "animal.h"
#include <iostream>

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;
}

그래서 당신이 도서관을 컴파일 할 때, 당신은animal.cppC++ 컴파일러를 사용합니다.그런 다음 C 코드로 링크하고 다음을 사용할 수 있습니다.animal_xxx기능들.

의 사용에 주의합니다.struct animal그리고.Animal.Animal는 일반적인 C++ 유형입니다.그것은 정확히 보이는 것과 같습니다.struct animal반면에, 는 "심각한" 유형입니다.이것은 C 프로그램이 그것이 거기에 있는 것을 볼 수 있고, 그것을 가질 수 있지만, 그것은 그것 안에 무엇이 있는지 모른다는 것을 의미합니다.그것이 아는 것은 그것이 필요한 기능을 가지고 있다는 것입니다.struct animal*.

실제 라이브러리에서는 메모리 할당을 위한 사용자 지정 지점이 필요합니다.여기가 도서관이라고 가정하면libjungle아마 적어도 당신은 원할 것입니다.jungle_setmalloc그리고.jungle_setfree합리적인 채무 불이행으로그런 다음 글로벌을 설정할 수 있습니다.new그리고.deletelibjungle사용자 정의 함수를 사용하기 위한 의 C++ 코드입니다.

이것은 전적으로 가능합니다.방법은 다음과 같습니다. 1.)Cplusiness를 포함하지 않는 C API를 가진 헤더.h가 있습니다.

#ifndef MIXEDCCPP_H
#define MIXEDCCPP_H

#ifdef __cplusplus
extern "C" {
#endif
#include <stdint.h> // Any C-compatible headers will go here.

// C API goes here.  C Functions can't contain any CPPiness.
void myclass_setName( void *pClassObj, const char *pName, int nameLen );

#ifdef __cplusplus
}
#endif

#ifdef __cplusplus

// Stuff that is only compatible with CPP goes here
// __cplusplus section won't get processed while compiling C files.

#include <vector> // CPP headers.


class MyClass {
   // Classes etc.
};
#endif // #ifdef __cplusplus

#endif // MIXEDCCPP_H

그런 다음 .cpp에서 CPP를 바로 포함할 수 있는 C-API 함수를 만들기만 하면 됩니다.

#include "mixedccpp.h"

extern "C" {
// C API goes here.  C Functions can't contain any CPPiness in their prototypes.
void myclass_setName( void *pClassObj, const char *pName, int nameLen )
{
    // But CPP knowledge can go inside the function - no problem, since this is a CPP file.
    MyClass *pMyClass = static_cast<MyClass *>(pClassObj);
    pMyClass->setName( pName, nameLen );
}

} // #extern "C"


// CPP Stuff goes here... or vice-versa.

이 경우 외부 라이브러리를 호출하기 때문에 헤더에 CPP 코드를 선언할 필요가 없습니다.그러나 CPP 라이브러리를 호출할 수 있는 C 호환 기능을 CPP 파일에 만들어야 합니다.C 파일에서 호출해야 하는 함수에 대해 외부 "C"를 사용한 다음 클래스 대신 C 구조체를 사용하고, 클래스가 필요한 경우 void *를 사용하여 C 함수에서 해당 클래스로 다시 캐스트합니다.표준 makefile은 .cpp 파일을 .cpp로 컴파일하고 외부 "C" {}을(를) 이해한다고 가정할 때 이를 올바르게 컴파일할 수 있어야 합니다.

는 C C++를할 수 .<string>C++ 로 선언되도록 해야 .extern "C"C 컴파일러에서 인식되는 유형만 사용합니다.

또한 코드가 C++에 있는 경우 C++ 컴파일러와 연결해야 합니다.로더 옵션을 올바르게 설정하는 데 많은 에너지를 소비할 준비가 되어 있다면 다른 방법으로 할 수 있지만 C++ 컴파일러를 사용하는 것이 훨씬 더 간단합니다.

gcc -c cmain.c
g++ -fPIC -shared -o cppfile.so cppfile.cpp
g++ -o cmain cmain.o cppfile.so

물론 다음을 수행해야 합니다.

  1. 더하다#include <stdio.h>cmain.c.
  2. 사용하다std::string S(filename);cppfile.cpp.

또한 인수 없이 프로그램을 호출하면 다음과 같은 결과를 얻을 수 있습니다.

$ ./cmain
terminate called throwing an exceptionAbort trap: 6
$ ./cmain x3
0
$

테스트 프로그램에서도 오용을 방지해야 합니다.

언급URL : https://stackoverflow.com/questions/14917952/can-i-use-shared-library-created-in-c-in-a-c-program

반응형