문제

일부 처리를 사용자 정의하기 위해 등록하려면 콜백 함수가 필요한 C 라이브러리가 있습니다. 콜백 함수의 유형입니다 int a(int *, int *).

다음과 유사한 C ++ 코드를 작성하고 C ++ 클래스 기능을 콜백 함수로 등록하려고합니다.

class A {
  public:
   A();
   ~A();
   int e(int *k, int *j);
};

A::A()
{
   register_with_library(e)
}

int
A::e(int *k, int *e)
{
  return 0;
}

A::~A() 
{

}

컴파일러는 다음 오류를 던집니다.

In constructor 'A::A()',
error:
 argument of type ‘int (A::)(int*, int*)’ does not match ‘int (*)(int*, int*)’.

내 질문 :

  1. 우선 내가하려는 것처럼 C ++ 클래스 Memeber 기능을 등록 할 수 있습니다. 그렇다면 어떻게해야합니까? (나는 32.8 at을 읽었다 http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html. 그러나 내 생각에 그것은 문제를 해결하지 못한다)
  2. 이것을 다루는 대체/더 좋은 방법이 있습니까?
도움이 되었습니까?

해결책

멤버 함수가 정적 인 경우 그렇게 할 수 있습니다.

클래스 A의 비 정적 멤버 함수에는 암시 적 첫 번째 유형 매개 변수가 있습니다. class A* 이에 해당합니다 이것 바늘. 그렇기 때문에 콜백의 서명에 첫 번째 매개 변수가있는 경우에만 등록 할 수 있습니다. class A* 유형.

다른 팁

멤버 함수가 정적이 아닌 경우이 작업을 수행 할 수 있지만 조금 더 작업이 필요합니다 (또한 참조하십시오. C ++ 기능 포인터를 C 함수 포인터로 변환합니다):

#include <stdio.h>
#include <functional>

template <typename T>
struct Callback;

template <typename Ret, typename... Params>
struct Callback<Ret(Params...)> {
   template <typename... Args> 
   static Ret callback(Args... args) {                    
      func(args...);  
   }
   static std::function<Ret(Params...)> func; 
};

template <typename Ret, typename... Params>
std::function<Ret(Params...)> Callback<Ret(Params...)>::func;

void register_with_library(int (*func)(int *k, int *e)) {
   int x = 0, y = 1;
   int o = func(&x, &y);
   printf("Value: %i\n", o);
}

class A {
   public:
      A();
      ~A();
      int e(int *k, int *j);
};

typedef int (*callback_t)(int*,int*);

A::A() {
   Callback<int(int*,int*)>::func = std::bind(&A::e, this, std::placeholders::_1, std::placeholders::_2);
   callback_t func = static_cast<callback_t>(Callback<int(int*,int*)>::callback);      
   register_with_library(func);      
}

int A::e(int *k, int *j) {
   return *k - *j;
}

A::~A() { }

int main() {
   A a;
}

이 예제는 다음과 같이 컴파일한다는 의미에서 완료됩니다.

g++ test.cpp -std=c++11 -o test

당신은 필요합니다 c++11 깃발. 코드에서 당신은 그것을 볼 수 있습니다 register_with_library(func) 장소라고합니다 func 정적 함수는 멤버 함수에 동적으로 바인딩됩니다. e.

문제는 그 메소드! = 함수입니다. 컴파일러는 방법을 다음과 같은 것으로 변환합니다.

int e( A *this, int *k, int *j );

따라서 클래스 인스턴스를 인수로 전달할 수 없기 때문에 통과 할 수 없습니다. 작업하는 한 가지 방법은 방법을 정적으로 만드는 것입니다.이 방법은 좋은 유형을 가질 것입니다. 그러나 클래스 인스턴스는 아니며 비 정적 클래스 멤버에 대한 액세스가 아닙니다.

다른 방법은 처음으로 A에 대한 정적 포인터가있는 함수를 선언하는 것입니다. 함수는 클래스로 호출을 리디렉션합니다.

int callback( int *j, int *k )
{
    static A  *obj = new A();
    a->(j, k);
}

그런 다음 콜백 함수를 등록 할 수 있습니다.

글쎄 ... 만약 당신이 Win32 플랫폼에 있다면 항상 불쾌한 멍청한 길이 있습니다 ...

Win32의 Thunking : 비 정적 멤버 함수로 콜백을 단순화합니다.

솔루션이지만 사용하지 않는 것이 좋습니다.
그것은 좋은 설명을 가지고 있으며 그것이 존재한다는 것을 아는 것이 좋습니다.

멤버 함수를 사용하는 데있어 문제는 행동 할 객체가 필요하고 C는 객체에 대해 알지 못한다는 것입니다.

가장 쉬운 방법은 다음을 수행하는 것입니다.

//In a header file:
extern "C" int e(int * k, int * e);

//In your implementation: 
int e(int * k, int * e) { return 0; }
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top