Ошибка преобразования void (__cdecl MyClass :: *) () в void *

Я пытаюсь связаться с внешней библиотекой в ​​моем приложении QT. Внешняя библиотека имеет заголовочный файл со следующим соответствующим кодом, который я пытаюсь вызвать:

 extern VGRABDEVICE_API bool V_AssignFrameSizeCallback(IGrabChannel* pChannel, void* pFunc);

В представленной демонстрационной программе C ++, которая не имеет проблем с компиляцией, следующий соответствующий код:

// in main.cpp
void _stdcall MyFrameSizeCallback(T x) {
do_stuff;
}

int main(int argc, char* argv[]) {
IGrabChannel* pChannel0 = something;
V_AssignFrameSizeCallback(pChannel0, MyFrameSizeCallback);
}

Я пытаюсь включить этот код в мое приложение QT, но получаю проблемы. В моем файле mainwindow.cpp:

void _stdcall MainWindow::MyFrameSizeCallback(T x) {
do_stuff;
}

void MainWindow::someFunction() {
IGrabChannel* pChannel0 = something;
V_AssignFrameSizeCallback(pChannel0, &MainWindow::MyFrameSizeCallback);
}

Я получаю ошибку:

error: C2664: 'bool V_AssignFrameSizeCallback(IGrabChannel *,void *)' :
cannot convert argument 2 from 'void (__cdecl MainWindow::* )(T)' to 'void *'
There is no context in which this conversion is possible

Что мне нужно сделать? Благодарю.

0

Решение

У тебя две проблемы. Первый, void* это указатель данных, а не указатель на функцию. В соответствии со стандартом C ++ приведение между ними не должно работать. Некоторые платформы предоставляют более надежную гарантию … например, Windows GetProcAddress и * nix dlsym смешайте два.

Далее ваш &MainWindow::MyFrameSizeCallback это не указатель на функцию, это указатель начлен-функция. Для вызова требуется MainWindow объект, о котором внешняя библиотека ничего не знает.

Вы должны предоставить библиотеке обычную функцию, а не функцию-член. Если у вас есть какой-то способ получить MainWindow* указатель объекта, затем вы можете вызвать его функцию-член для выполнения реальной работы. Иногда библиотека предоставляет параметр «context», который передается вашему обратному вызову; это отличное место для размещения указателя объекта. В противном случае вам нужно будет хранить ваши MainWindow* в глобальной переменной. Легко, если у вас есть только один, а если у вас есть больше, вы можете пойти с std::map<IGrabChannel*, MainWindow*>,

Код:

MainWindow* MainWindow::the_window;

void MainWindow::MyFrameSizeCallback(T x)
{
do_stuff;
}

void _stdcall MyFrameSizeCallbackShim(T x)
{
MainWindow::the_window->MyFrameSizeCallback(x);
}

void MainWindow::someFunction()
{
IGrabChannel* pChannel0 = something;
the_window = this;
V_AssignFrameSizeCallback(pChannel0, &MyFrameSizeCallbackShim);
}

Если параметр x не является IGrabChannel, измените тип данных карты и логику вставки соответственно. Если параметр x не какой-то уникальный предсказуемый идентификатор, вы можете ограничиться только обратными вызовами одного MainWindow пример.

2

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


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