Используя функцию членства класса C++ как функция обратного вызова C

Как работают иконки Webfont

Значки Webfonts работают с помощью CSS для вставки определенного глифа в HTML с использованием свойства content. Затем он использует @ font-face для загрузки веб-сайта dingbat, который стилирует введенный глиф. Результатом является то, что введенный глиф становится желаемым значком.

Для начала вам понадобится файл webfont с нужными значками, либо определенный для определенных символов ASCII (A, B, C,!, @, # и т. д.) или в области частного использования шрифта Unicode, которые являются пробелами в шрифте, которые не будут использоваться конкретными символами в кодированном кодировке Unicode.

blockquote>

Здесь вы можете прочитать, как создать значок webfont -> link

44
задан sharptooth 16 June 2009 в 10:45
поделиться

5 ответов

Вы можете сделать это, если функция-член является статической.

Нестатические функции-члены класса A имеют неявный первый параметр типа class A * , который соответствует этому указателю. Вот почему вы могли зарегистрировать их только в том случае, если в сигнатуре обратного вызова также был первый параметр типа class A * .

41
ответ дан 26 November 2019 в 21:20
поделиться

В этом решении у нас есть шаблонный класс со статическим методом, который будет дан "c функция" как обратный вызов. Этот класс содержит "обычный" объект (с функцией членства, названной обратным вызовом (), который наконец назовут).

, Как только Ваш класс (здесь, A) определяется, он может легко использоваться:

int main() {

  Holder<A> o ( A(23, 23) );

  std::cout << o().getN() << "\n";

  callACFunctionPtr( fun );

  callACFunctionPtr( o.callback );

} // ()

Полный пример:

#include <iostream>

// ----------------------------------------------------------
// library class: Holder
// ----------------------------------------------------------
template< typename HeldObjectType >
class Holder {
public:
  static inline HeldObjectType object;

  static void callback( ) {
    object.callback();
  } // ()

  HeldObjectType &  operator() ( ) {
    return object;
  }

  Holder( HeldObjectType && obj )
  {
    object = obj;
  }

  Holder() = delete;

}; // class

// ----------------------------------------------------------
// "old" C function receivin a ptr to function as a callback
// ----------------------------------------------------------
using Callback = void (*) (void);

// ..........................................................
// ..........................................................
void callACFunctionPtr( Callback f ) {
  f();
} // ()

// ----------------------------------------------------------
// ----------------------------------------------------------
void fun() {
  std::cout << "I'm fun\n";
} // 

// ----------------------------------------------------------
// 
// Common class where we want to write the
// callback to be called from callACFunctionPtr.
// Name this function: callback
// 
// ----------------------------------------------------------
class A {
private:
  int n;

public:

  A(  ) : n( 0 ) { }

  A( int a, int b ) : n( a+b ) { }

  void callback( ) {
    std::cout << "A's callback(): " << n << "\n";
  }

  int getN() {
    return n;
  }

}; // class

// ----------------------------------------------------------
// ----------------------------------------------------------
int main() {

  Holder<A> o ( A(23, 23) );

  std::cout << o().getN() << "\n";

  callACFunctionPtr( fun );

  callACFunctionPtr( o.callback );

} // ()
0
ответ дан 26 November 2019 в 21:20
поделиться

Проблема в том, что метод! = Функция. Компилятор преобразует ваш метод в нечто подобное:

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

Итак, он уверен, что вы не можете передать его, потому что экземпляр класса не может быть передан в качестве аргумента. Один из способов обойти эту проблему - сделать метод статическим, чтобы у него был хороший тип. Но не будет никакого экземпляра класса и доступа к нестатическим членам класса.

Другой способ - объявить функцию со статическим указателем на A, инициализированным в первый раз. Функция только перенаправляет вызов в класс:

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

Затем вы можете зарегистрировать функцию обратного вызова.

6
ответ дан 26 November 2019 в 21:20
поделиться

Ну ... если вы используете платформу win32, всегда есть неприятный способ Thunking ...

Thunking в Win32: упрощение обратных вызовов для нестатических функций-членов

Это решение, но я не рекомендую его использовать.
У этого есть хорошее объяснение, и приятно знать, что оно существует.

5
ответ дан 26 November 2019 в 21:20
поделиться

Проблема с использованием функции-члена заключается в том, что ей нужен объект, с которым можно действовать, а C не знает об объектах.

Самый простой способ - это сделать следующее:

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

//In your implementation: 
int e(int * k, int * e) { return 0; }
1
ответ дан 26 November 2019 в 21:20
поделиться