C에서 C++를 우아하게 호출하다
우리는 몇 가지 프로젝트를 평이하게 전개한다.C
(C99). 단, 소스코드(수학 라이브러리)로서 라이브러리 1개가 있습니다.C++
이 라이브러리가 필요하기 때문에 이 소스코드를 통합하는 가장 우아한 방법은 무엇일까요?
크기 간 비율C
그리고.C++
이20:1
그래서 로 이동한다C++
선택사항이 아닙니다.정적 라이브러리를 사용할까요? DLL? (모두 Windows에 있습니다.)
편집: 코멘트에 기재되어 있는 내용에 근거해, C호환으로 분할하는 것을 지적합니다.struct duck
및 파생된class Duck
아마 불필요할 겁니다.구현은 아마 안전하게 에 삽입할 수 있을 것입니다.struct duck
제거하다class Duck
이 때문에 불필요합니다.real(…)
하지만 저는 C++에 대해 잘 모릅니다(특히 C가 C 우주와 상호작용하는 방식).
단순히 모든 C와 C++ 코드를 하나의 바이너리로 링크할 수 없는 이유는 없습니다.
C++ 코드에 인터페이스 하려면 C++ API를 C API로 랩해야 합니다.내부 함수를 여러 개 선언하면 이 작업을 수행할 수 있습니다.extern "C" { ... }
C++ 코드를 컴파일 할 때 및 C 클라이언트 코드를 컴파일 할 때 외부 선언을 하지 않습니다.예:
#ifdef __cplusplus
extern "C" {
#endif
typedef struct duck duck;
duck* new_duck(int feet);
void delete_duck(duck* d);
void duck_quack(duck* d, float volume);
#ifdef __cplusplus
}
#endif
C++ 소스에서 오리 구조를 정의할 수 있으며, 실제 오리 구조를 상속할 수도 있습니다.Duck
class from it:
struct duck { };
class Duck : public duck {
public:
Duck(int feet);
~Duck();
void quack(float volume);
};
inline Duck* real(duck* d) { return static_cast<Duck*>(d); }
duck* new_duck(int feet) { return new Duck(feet); }
void delete_duck(duck* d) { delete real(d); }
void duck_quack(duck* d, float volume) { real(d)->quack(volume); }
duck structure에서 상속을 원하는 유일한 이유는 C API의 속성에 일부를 노출하기 위해서입니다.이것은 일반적으로 나쁜 스타일로 간주됩니다.상속을 하지 않으면 C 헤더는 다음과 같이 됩니다.
struct Duck;
struct Duck* new_Duck(int feet);
void delete_Duck(struct Duck* d);
void Duck_quack(struct Duck* d, float volume);
이는 유형 캐스팅이 필요 없는 해당 구현입니다.
extern "C" {
#include "Duck.h"
}
class Duck {
public:
Duck(int feet) : {}
~Duck() {}
void quack(float volume) {}
};
struct Duck* new_Duck(int feet) { return new Duck(feet); }
void delete_Duck(struct Duck* d) { delete d; }
void Duck_quack(struct Duck* d, float volume) { d->quack(volume); }
마찬가지로 C++ 인터페이스(순수 가상 클래스)와 그 실장용으로 C API를 작성할 수 있습니다.이 경우 컨스트럭터만 구체적인 구현에 기초하면 됩니다(예를 들어 new_RubberDuck(2)).디스트럭터 및 기타 모든 함수는 C++와 같이 올바른 구현에서 자동으로 동작합니다.
C++ 연산 라이브러리는 유틸리티 클래스의 용으로 실장할 수 있습니다(스태틱멤버만).이 경우 훨씬 더 간단한 접근법을 취할 수 있습니다.
class FPMath {
public:
static double add(double, double);
static double sub(double, double);
static double mul(double, double);
static double div(double, double);
};
C 인터페이스의 헤더는 다음과 같습니다.
double FPMath_add(double, double);
double FPMath_sub(double, double);
double FPMath_mul(double, double);
double FPMath_div(double, double);
대응하는 실장은 다음과 같습니다.
double FPMath_add(double a, double b) { return FPMath::add(a, b); }
double FPMath_sub(double a, double b) { return FPMath::sub(a, b); }
double FPMath_mul(double a, double b) { return FPMath::mul(a, b); }
double FPMath_div(double a, double b) { return FPMath::div(a, b); }
하지만 어쩌면 이건 당연한 걸 말하는 것일 수도 있어...
일부 객체의 멤버 함수를 직접 호출할 수 있는 "해크"를 만드는 방법이 있습니다.
할 은 '만들기'를 입니다.extern "C"
출하시 함수: 포인터를 합니다(「」로서).void*
을 사용하다
두 번째로 필요한 것은 멤버 기능의 이름이 뒤죽박죽이 되어 있는 것입니다.
그런 다음 망진된 이름을 사용하여 함수를 호출할 수 있으며 공장에서 반환된 포인터를 첫 번째 인수로 전달합니다.
경고:
- 물론 다른 오브젝트, 참조, 기타 C++를 필요로 하는 멤버 호출 함수나 C타입과 호환되지 않는 오브젝트 또는 타입을 반환하는 함수는 동작하지 않습니다.
- 호출되는 가상 함수가 아니더라도 가상 함수가 포함된 개체에서는 작동하지 않습니다.
- 뭉개진 이름은 유효한 C 기호여야 합니다.
- 더 많은...
이것은 추천할 만한 것이 아닙니다.사실 그 반대입니다.저는 이 답변에 나와 있는 것과 같은 것을 하지 말 것을 강력히 권합니다.이는 지원되지 않고 아마도 정의되지 않은 행동이며 이상하고 예측할 수 없는 방식으로 부서질 수 있습니다.
언급URL : https://stackoverflow.com/questions/7281441/elegantly-call-c-from-c
'programing' 카테고리의 다른 글
속성 합계를 위해 객체 배열에 대한 감소를 호출하려면 어떻게 해야 합니까? (0) | 2022.10.11 |
---|---|
Python 3 회전 범위를 목록으로 설정 (0) | 2022.10.11 |
java.displaces를 클릭합니다.예외:JUnit 실행에 실행 가능한 메서드 예외가 없습니다. (0) | 2022.10.11 |
문자열을 대문자로 변경하는 방법 (0) | 2022.10.11 |
컬렉션에서 최대값을 얻는 방법(예를 들어 Array List) (0) | 2022.10.11 |