program tip

C에서 C ++ 함수를 호출하는 방법은 무엇입니까?

radiobox 2020. 10. 27. 08:02
반응형

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를 만들어야합니다. 기본적으로 extern "C"로 선언되고 C ++ 라이브러리를 래핑하는 순수 C API (예 : 클래스를 사용하지 않음)가있는 C ++ 코드를 작성해야합니다. 그런 다음 생성 한 순수 C 래퍼 라이브러리를 사용합니다.

C가 객체 지향이 아니더라도 C API는 선택적으로 객체 지향 스타일을 따를 수 있습니다. 전의:

 // *.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.h, aaa.cpp 파일에 정의 된 AAA 라는 C ++ 클래스 가 있고 AAA 클래스 에 C 코드에 대해 활성화하려는 sayHi (const char * name) 라는 메서드가 있다고 가정 합니다.

클래스 AAA 의 C ++ 코드 -순수 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 커넥터를 만듭니다. aaa_c_connector.h, aaa_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 define C functions that are able to call C++ code

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

Compiling it using a C compilation command:

gcc main.c -L. -laaa_c_connector -o c_aaa

I will need to set LD_LIBRARY_PATH to contain $PWD, and if I run the executable ./c_aaa, I will get the output I expect:

Hi David
Hi James

EDIT:

On some linux distributions, -laaa and -lstdc++ may also be required for the last compilation command. Thanks to @AlaaM. for the attention


Assuming the C++ API is C-compatible (no classes, templates, etc.), you can wrap it in extern "C" { ... }, just as you did when going the other way.

If you want to expose objects and other cute C++ stuff, you'll have to write a wrapper API.


You will have to write a wrapper for C in C++ if you want to do this. C++ is backwards compatible, but C is not forwards compatible.


export your C++ functions as extern "C" (aka C style symbols), or use the .def file format to define undecorated export symbols for the C++ linker when it creates the C++ library, then the C linker should have no troubles reading it


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

You can prefix the function declaration with extern “C” keyword, e.g.

extern “C” int Mycppfunction()

{

// Code goes here

return 0;

}

For more examples you can search more on Google about “extern” keyword. You need to do few more things, but it's not difficult you'll get lots of examples from Google.

참고URL : https://stackoverflow.com/questions/2744181/how-to-call-c-function-from-c

반응형