resueltos que programacion polimorfismo orientada objetos objeto herencia ejercicios ejemplos constructores codigo clases c++ c interop callback

que - Usar una función de miembro de clase C++ como función de devolución de llamada C



programacion orientada a objetos ejemplos c++ (5)

Bueno ... si estás en una plataforma win32, siempre está la desagradable manera Thunking ...

Thunk en Win32: Simplificación de devoluciones de llamadas a funciones miembro no estáticas

Es una solución pero no recomiendo usarla.
Tiene una buena explicación y es bueno saber que existe.

Tengo una biblioteca C que necesita una función de devolución de llamada para registrarse y personalizar algunos procesos. El tipo de la función de devolución de llamada es int a(int *, int *) .

Estoy escribiendo código C ++ similar al siguiente y trato de registrar una función de clase C ++ como la función de devolución de llamada:

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() { }

El compilador arroja el siguiente error:

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

Mis preguntas:

  1. En primer lugar, es posible registrar una función de memeber de la clase C ++ como lo estoy intentando hacer y, en caso afirmativo, ¿cómo? (Leí 32.8 en http://www.parashift.com/c++-faq-lite/mixing-c-and-cpp.html . Pero en mi opinión no resuelve el problema)
  2. ¿Hay una forma alternativa / mejor de abordar esto?

El problema con el uso de una función miembro es que necesita un objeto sobre el que actuar, y C no conoce los objetos.

La forma más fácil sería hacer lo siguiente:

//In a header file: extern "C" int e(int * k, int * e); //In your implementation: int e(int * k, int * e) { return 0; }


El problema es ese método! = Función. El compilador transformará su método a algo así:

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

Por lo tanto, es seguro que no puede pasarlo, porque la instancia de la clase no se puede pasar como argumento. Una forma de evitar el problema es hacer que el método sea estático, de esta forma tendría el tipo correcto. Pero no habrá ninguna instancia de clase ni acceso a miembros de clase no estáticos.

La otra forma es declarar una función con un puntero estático a un A inicializado la primera vez. La función solo redirige la llamada a la clase:

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

Entonces puede registrar la función de devolución de llamada.


Puede hacerlo si la función miembro es estática.

Las funciones miembro no estáticas de clase A tienen un primer parámetro implícito de tipo class A* que corresponde a este puntero. Es por eso que solo podía registrarlos si la firma de la devolución de llamada también tenía el primer parámetro del tipo de class A* .


También puede hacer esto si la función miembro no es estática, pero requiere un poco más de trabajo (consulte también Convertir puntero de función C ++ en puntero de función 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; }

Este ejemplo está completo en el sentido de que compila:

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

Necesitarás la bandera c++11 . En el código se ve que se llama register_with_library(func) , donde func es una función estática vinculada dinámicamente a la función miembro e .