Как получить & quot; простой & quot; указатель на функцию из функции-члена

У меня проблема с указателями на функции, и ничто из того, что я нашел в сети, не помогло мне решить эту проблему.

У меня есть функция из C API, которая берет указатель на функцию void:

extern int APIFunction(int, void (*func)(int));

У меня есть класс с функцией, которую я хотел бы поставить, когда я вызываю функцию API.

class MyClass
{
public:
void myFunction(int status, otherAPi arguments...);
};

Затем я создал указатель на мою функцию-член и создал новый экземпляр моего класса

typedef  void (MyClass::*MyClassFunctionPointer)(int stat, otherAPi arguments...);
MyClassFunctionPointer fctPointer= &MyClass::myFunction;
LicenseSecurity instance;

Я получаю сообщение об ошибке при попытке вызвать функцию APi с указателем функции, который я создал:

int stat = APIFunction(5, fctPointer ); // -> error 1
int stat = APIFunction(5, instance.*fctPointer ); // -> error 2

Я получил ошибки соответственно в первом и втором случае:

E2034 Impossible to convert 'void (MyClass::*)(int, otherAPITypes...)' into 'void (*) (int, otherAPITypes...)'
E2342 Bad type correspondence in the parameter 'func' ('void (*)(int, otherAPITypes...)' desired, 'void(int, otherAPITypes...)' obtained)

У меня нет доступа к функции API, поэтому я не могу ее изменить. Резюмируя проблему: как получить «простой» указатель на функцию C для указания аргумента функции из функции-члена моего класса?

Спасибо

0

Решение

К сожалению, вы не можете. Сожалею.

В идеале, ваш API будет принимать что-то вроде std::function это позволит вам обернуть свободные функции или функции-члены. Но если вы не можете изменить API, у вас нет другого выбора, кроме как предоставить бесплатную функцию.

2

Другие решения

Вы не можете получить «простой» указатель функции на нестатическую функцию-член, потому что функция требует указатель this при вызове. Если бы вы создали такой указатель на функцию, то при вызове функции не было бы этого указателя для ссылки.

0

С таким древним C API, к сожалению, у вас нет никакого способа сделать это.

Что вам нужно сделать, это сделать статическую функцию или функцию, не являющуюся членом, чтобы принимать обратный вызов, а затем выяснить, какой экземпляр объекта вызывать член. Некоторые C API позволяют передавать пользовательские данные в обратный вызов, и в этом случае вы используете их для хранения this указатель в вопросе. Если это не вариант, вы можете использовать глобальный или одноэлементный объект и разрешить регистрацию только одного такого обратного вызова.

0

Вы можете объявить обратный вызов как отдельную функцию или как статический метод класса. Сложная часть обращается к указателю экземпляра класса внутри обратного вызова.

В идеале, хорошо разработанный API позволяет указывать пользовательское значение для обратных вызовов. Это позволяет вам легко передавать экземпляр класса и получать к нему доступ непосредственно внутри функции обратного вызова. Но, похоже, вы не работаете с таким API, поэтому вам нужно использовать обходной путь.

Если у вас одновременно используется только 1 экземпляр класса, вы можете сохранить указатель экземпляра в глобальной переменной, а для обратного вызова использовать глобальную переменную для доступа к экземпляру.

Но если у вас есть несколько экземпляров классов, используемых одновременно, вы ищете подходящее решение, похожее на VCL. MakeObjectInstance() функция, которая позволяет TWndMethod-подписанные методы класса, которые будут использоваться в качестве обратных вызовов процедур окна Win32. По сути, блок исполняемой памяти выделяется динамически, код блока-заглушки записывается в блок, а указатель экземпляра и указатель метода класса также сохраняются в блоке. Затем блок передается в API, как если бы это был указатель на функцию. Когда API вызывает «функцию», исполняется код заглушки, который должен управлять стеком вызовов и регистрами ЦП, чтобы вызывать указатель на метод сохраненного класса, передавая указатель на сохраненный экземпляр как его скрытый this параметр, сохраняя семантику других параметров, стек вызовов, результат функции и т. д.

Ничто в C ++ на самом деле не обеспечивает такого рода громадного подхода. Это не сложно реализовать вручную, но это также не тривиально (взгляните на исходный код для MakeObjectInstance() в исходном файле Classes.pas VCL). Самым сложным является создание необходимого кода-заглушки, который соответствует семантике сигнатуры вашего метода класса.

0
По вопросам рекламы [email protected]