Мой обычный способ решения этой проблемы - создать статическую функцию в моем классе, которая принимает явный указатель this
в качестве параметра, а затем просто вызывает функцию-член. Иногда вместо этого статической функции необходимо точно следовать сигнатуре типа, которую библиотека C ожидает для обратного вызова, и в этом случае я преобразую void *
, который обычно встречается в таких случаях, в указатель this
, который мне действительно нужен, затем вызываю функцию-член.
Если у API нет средства для предоставления ему void *
, который затем будет возвращен вашему обратному вызову, этот API сломан и требует исправления. Если вы не можете это исправить, есть варианты, включающие глобальные (или их двоюродный брат static
) переменные. Но они безобразны.
В какой-то момент я создал довольно хакерскую систему шаблонов для создания переменных такого типа и привязки к ним статической функции, которую вы могли бы затем передать вещам с таким API. Но я должен был пойти на это, и я не совсем уверен, что это дает какую-то выгоду по сравнению с простым старым глобалом.
Решение, основанное на этой идее без использования шаблонов, будет выглядеть примерно так:
class InstanceBinder1 {
public:
static initialize(thisClass *instance, int (thisClass::*processor)(char *buf, int a)) {
instance_ = instance;
processor_ = processor;
}
static int processor(char *instance, int a) {
instance_->*processor_(buf, a);
}
private:
static thisClass *instance_;
static int (thisClass::*processor_)(char *buf, int a);
};
Тогда вы могли бы передать &InstanceBinder1::processor
в библиотеку C.
Вам нужно будет создать новый класс этого типа для каждого отдельного экземпляра thisClass
, в который вам нужна библиотека C для вызова. Это означает, что число этих экземпляров будет определено во время компиляции, и нет никакого способа обойти это.