IT이야기

C에서 C++ 함수를 호출하는 방법은?

cyworld 2022. 4. 23. 10:27
반응형

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

반응형