C 프로그램에서 C++로 만든 공유 라이브러리를 사용할 수 있습니까?
저는 C를 이용하여 프로그램을 만들고 있습니다.하지만 저는 C++ 전용 API가 있는 라이브러리를 많이 사용해야 합니다.그렇다면 C++에서 공유 객체를 생성한 다음 C를 사용하여 해당 기능에 액세스할 수 있습니까?
- 제가 전달하고 반환할 데이터는 C 호환 데이터 유형뿐입니다.
- 여기서는 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.cpp
C++ 컴파일러를 사용합니다.그런 다음 C 코드로 링크하고 다음을 사용할 수 있습니다.animal_xxx
기능들.
의 사용에 주의합니다.struct animal
그리고.Animal
.Animal
는 일반적인 C++ 유형입니다.그것은 정확히 보이는 것과 같습니다.struct animal
반면에, 는 "심각한" 유형입니다.이것은 C 프로그램이 그것이 거기에 있는 것을 볼 수 있고, 그것을 가질 수 있지만, 그것은 그것 안에 무엇이 있는지 모른다는 것을 의미합니다.그것이 아는 것은 그것이 필요한 기능을 가지고 있다는 것입니다.struct animal*
.
실제 라이브러리에서는 메모리 할당을 위한 사용자 지정 지점이 필요합니다.여기가 도서관이라고 가정하면libjungle
아마 적어도 당신은 원할 것입니다.jungle_setmalloc
그리고.jungle_setfree
합리적인 채무 불이행으로그런 다음 글로벌을 설정할 수 있습니다.new
그리고.delete
에libjungle
사용자 정의 함수를 사용하기 위한 의 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
물론 다음을 수행해야 합니다.
- 더하다
#include <stdio.h>
cmain.c
. - 사용하다
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
'programing' 카테고리의 다른 글
Gradle 아카이브에 65535개가 넘는 항목이 포함 (0) | 2023.07.22 |
---|---|
방법을 이해합니다.내부 C 함수는 R에서 처리됩니다. (0) | 2023.07.22 |
Firebase 3에서 토큰에 대한 서버 측 검증이 여전히 가능합니까? (0) | 2023.07.22 |
Oracle 및 JDBC 성능:INSERT ALL vs prepared Statement.addBatch (0) | 2023.07.22 |
org.postgresql.dll.PSQL 예외: 오류: 값이 너무 깁니다(255). 형식 문자가 다양합니다(255) (0) | 2023.07.22 |