C에서 C++ 함수를 호출하는 방법은?
나는 이걸 알고 있다.
C++에서 C 함수 호출:
만약 내 지원서가 C++에 있다면, 나는 C로 쓰여진 도서관에서 기능을 불러야 했다.그렇다면 나는 이렇게 했을 것이다.
//main.cpp
extern "C" void C_library_function(int x, int y);//prototype
C_library_function(2,4);// directly using it.
그렇다고 해서 그 이름이 엉망이 되지는 않을 것이다.C_library_function
링커는 입력된 *.lib 파일에서 동일한 이름을 찾으면 문제가 해결된다.
C에서 C++ 함수를 호출하는 중?
하지만 여기 C로 쓰여진 큰 어플리케이션을 확장하고 있는데 C++로 쓰여진 라이브러리를 사용해야 해.여기서 C++의 이름 망칭이 문제를 일으키고 있다.링커는 해결되지 않은 기호에 대해 불평하고 있다.C++ 컴파일러를 내 C프로젝트에 사용할 수 없어. 다른 많은 것들을 망가뜨리고 있거든.나가는 길은 무엇인가?
그런데 나는 MSVC를 사용하고 있다.
C++ 코드의 기능을 노출하기 위한 C API를 만들어야 한다.기본적으로 C++ 라이브러리를 감싸는 순수한 C API(예를 들어 클래스를 사용하지 않음)가 있는 외부 "C"로 선언된 C++ 코드를 작성해야 한다.그런 다음 생성한 순수 C 래퍼 라이브러리를 사용하십시오.
당신의 C API는 C가 객체지향적이지 않더라도 선택적으로 객체지향 스타일을 따를 수 있다.Ex:
// *.h file
// ...
#ifdef __cplusplus
#define EXTERNC extern "C"
#else
#define EXTERNC
#endif
typedef void* mylibrary_mytype_t;
EXTERNC mylibrary_mytype_t mylibrary_mytype_init();
EXTERNC void mylibrary_mytype_destroy(mylibrary_mytype_t mytype);
EXTERNC void mylibrary_mytype_doit(mylibrary_mytype_t self, int param);
#undef EXTERNC
// ...
// *.cpp file
mylibrary_mytype_t mylibrary_mytype_init() {
return new MyType;
}
void mylibrary_mytype_destroy(mylibrary_mytype_t untyped_ptr) {
MyType* typed_ptr = static_cast<MyType*>(untyped_ptr);
delete typed_ptr;
}
void mylibrary_mytype_doit(mylibrary_mytype_t untyped_self, int param) {
MyType* typed_self = static_cast<MyType*>(untyped_self);
typed_self->doIt(param);
}
나는 다음과 같은 방법으로 할 것이다.
(MSVC로 작업하는 경우 GCC 컴파일 명령을 무시하십시오.)
파일에 정의되어 있는 AAA라는 C++ 클래스가 있고 AAA 클래스에 sayHi(const char *name)라는 메서드가 있다고 가정해 보십시오.
클래스 AAA의 C++ 코드 - Pure C++, 나는 그것을 수정하지 않는다.
aaa.h
#ifndef AAA_H
#define AAA_H
class AAA {
public:
AAA();
void sayHi(const char *name);
};
#endif
aaa.cpp
#include <iostream>
#include "aaa.h"
AAA::AAA() {
}
void AAA::sayHi(const char *name) {
std::cout << "Hi " << name << std::endl;
}
C++에 대해 정기적으로 수행되는 대로 이 클래스를 컴파일하십시오.이 코드는 C 코드에 의해 사용될 것이라는 것을 "모른다".다음 명령 사용:
g++ -fpic -shared aaa.cpp -o libaaa.so
C++에서도 C 커넥터를 만드는 중:
파일 정의: aa_c_connector.h, aa_c_connector.cpp.이 커넥터는 AAA의 인스턴스를 사용하는 AAA_sayHi(cosnt char *name)라는 C 함수를 정의하고 그 방법을 다음과 같이 호출한다.
aaa_c_connector.h
#ifndef AAA_C_CONNECTOR_H
#define AAA_C_CONNECTOR_H
#ifdef __cplusplus
extern "C" {
#endif
void AAA_sayHi(const char *name);
#ifdef __cplusplus
}
#endif
#endif
aaa_c_connector.cpp
#include <cstdlib>
#include "aaa_c_connector.h"
#include "aaa.h"
#ifdef __cplusplus
extern "C" {
#endif
// Inside this "extern C" block, I can implement functions in C++, which will externally
// appear as C functions (which means that the function IDs will be their names, unlike
// the regular C++ behavior, which allows defining multiple functions with the same name
// (overloading) and hence uses function signature hashing to enforce unique IDs),
static AAA *AAA_instance = NULL;
void lazyAAA() {
if (AAA_instance == NULL) {
AAA_instance = new AAA();
}
}
void AAA_sayHi(const char *name) {
lazyAAA();
AAA_instance->sayHi(name);
}
#ifdef __cplusplus
}
#endif
일반 C++ 컴파일 명령을 사용하여 다시 컴파일:
g++ -fpic -shared aaa_c_connector.cpp -L. -laaa -o libaaa_c_connector.so
이제 나는 C 함수 AAA_sayHi(const char *name)를 구현하는 공유 라이브러리(libaaa_c_connector.so)가 있다.이제 C 기본 파일을 만들고 모두 함께 컴파일할 수 있다.
main.c
#include "aaa_c_connector.h"
int main() {
AAA_sayHi("David");
AAA_sayHi("James");
return 0;
}
C 컴파일 명령을 사용하여 컴파일:
gcc main.c -L. -laaa_c_connector -o c_aaa
$PWD를 포함하도록 LD_LIBRARY_PATH를 설정해야 하며, 실행 파일을 실행하면 ./c_aaaa에서 다음 예상 출력을 얻는다.
Hi David
Hi James
편집:
日本 리눅스가 있다.-laaa
그리고-lstdc++
마지막 컴파일 명령에도 필요할 수 있다.@AlaM 덕분에.주목하여
C++ API가 C-호환성(클래스, 템플릿 등 없음)이라고 가정할 경우 다음 형식으로 포장할 수 있다.extern "C" { ... }
네가 다른 길로 갈 때 그랬던 것처럼
물건 등 귀여운 C++ 물건을 노출하려면 래퍼 API를 써야 한다.
이렇게 하려면 C에 대한 포장지를 C++로 써야 할 것이다.C++는 역호환성이지만 C는 전진호환성이 없다.
C++ 기능을 외부 "C"(일명 C 스타일 기호)로 내보내거나, .def 파일 형식을 사용하여 C++ 라이브러리를 만들 때 C++ 링커에 대해 지정되지 않은 내보내기 기호를 정의하면 C 링커가 이를 읽는 데 문제가 없어야 한다.
#include <iostream>
//////////////
// C++ code //
//////////////
struct A
{
int i;
int j;
A() {i=1; j=2; std::cout << "class A created\n";}
void dump() {std::cout << "class A dumped: " << i << ":" << j << std::endl;}
~A() {std::cout << "class A destroyed\n";}
};
extern "C" {
// this is the C code interface to the class A
static void *createA (void)
{
// create a handle to the A class
return (void *)(new A);
}
static void dumpA (void *thisPtr)
{
// call A->dump ()
if (thisPtr != NULL) // I'm an anal retentive programmer
{
A *classPtr = static_cast<A *>(thisPtr);
classPtr->dump ();
}
}
static void *deleteA (void *thisPtr)
{
// destroy the A class
if (thisPtr != NULL)
{
delete (static_cast<A *>(thisPtr));
}
}
}
////////////////////////////////////
// this can be compiled as C code //
////////////////////////////////////
int main (int argc, char **argv)
{
void *handle = createA();
dumpA (handle);
deleteA (handle);
return 0;
}
함수 선언에 외부 "C" 키워드와 접두사를 붙일 수 있다(예:
외부 "C" in Mycppfunction()
{
// 코드는 여기로 이동
반환 0;
}
더 많은 예제를 위해 당신은 구글에서 "외부" 키워드에 대해 더 많이 검색할 수 있다.몇 가지 일을 더 해야 하지만, 구글에서 많은 예시를 얻을 수 있다는 것은 어렵지 않다.
참조URL: https://stackoverflow.com/questions/2744181/how-to-call-c-function-from-c
'IT이야기' 카테고리의 다른 글
Vue를 사용하여 API를 사용한 일괄 업데이트 (0) | 2022.04.23 |
---|---|
복잡한 선언문을 읽기 쉬운 규칙? (0) | 2022.04.23 |
vue 계산된 속성을 한 번만 실행하는 방법 (0) | 2022.04.23 |
테스트 라이브러리와 함께 적용되지 않는 SFC 스타일 (0) | 2022.04.23 |
Vue: v-for의 입력 배열에서 입력 변경에 대응 (0) | 2022.04.22 |