Я работаю над приложением, использующим Qt версии 4.8 в C ++.
Мне нужно использовать функцию C, которая требует указатель на свободную функцию:
void handler(int dummy)
Мне нужно изменить отображаемые значения в моем графическом интерфейсе в зависимости от того, что происходит внутри функции.
Итак, я читал о том, как преобразовать функцию-член в свободную функцию. Я обнаружил, что я могу сделать это, только если моя функция-член является статической.
Но я не могу сделать это статичным — я не смогу изменить какие-либо виджеты, если я сделаю это статичным.
Итак, как я могу справиться с проблемой? Как я могу передать нестатическую функцию-член в качестве указателя на свободную функцию. Если это невозможно, как обойти это?
Буду благодарен за любые предложения, отличающиеся тем, что использовать другую библиотеку.
Поскольку функция C принимает аргумент, вы можете использовать аргумент в качестве индекса в массиве функторов:
class MyWidget : public QWidget {
using vector_t = QVector<std::function<void()>>;
static vector_t m_functions;
public:
using function_type = void(*)(int);
using size_type = vector_t::size_type;
static function_type getHandler() {
return +[](int index){ MyWidget::m_functions[index]; };
}
template <typename F> static size_type getIndexFor(F && fun) {
m_functions.append(std::forward<F>(fun));
return m_functions.size() - 1;
}
//...
size_type getIndexForSetTitle();
};
getHandler
возвращает адрес функции-обработчика.
getIndexFor
возвращает аргумент, который будет передан обработчику для запуска заданного функтора. Функтор может инкапсулировать вызовы методов виджета. Здесь мы позвоним setWindowTitle
на виджете:
MyWidget::size_type MyWidget::getIndexForSetTitle() {
static size_type index = getIndexFor([this]{ setWindowTitle("Foo"); });
return index;
}
Да, C ++ не позволяет передавать функции-члены в виде указателя на библиотеку C.
В этом случае общий подход использует вспомогательную функцию, которая действует как мост между библиотекой C и нашим экземпляром класса. Эта вспомогательная функция является свободной функцией, которая получает указатель на текущий экземпляр класса и в своем теле вызывает соответствующий метод-член экземпляра класса.
void handler_helper(int data){
MyClass *obj = (MyClass *) data;
obj->handler(); // This is the corresponding member method
}
И где вы вызываете функцию из этой библиотеки C, вы должны передать handler_helper
в качестве указателя на функцию и (int) this
в качестве аргумента.