Передача указателя на функцию-член для варианта использования обратного вызова - PullRequest
1 голос
/ 24 января 2012

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

Я использую Qt и C ++.Сторонняя библиотечная функция выглядит как функция C.Пример кода, предоставленного третьей стороной, помещает весь код в main.Это нежелательно, мне нужно обернуть код в классах.

Как мне решить эту проблему с обратным вызовом?

А *

#include "ThirdPartyLibrary.h"
class A
{
public:
    QFile* f;

    A(QString filename);
    ~A();

    bool mount();

    BOOL _stdcall OnWriteCallback
    (
        DRIVE_HANDLE h, 
        ULONGLONG WriteOffset, 
        ULONG WriteSize, 
        const void* WriteBuffer, 
        ULONG *BytesWritten
    );

    BOOL _stdcall OnReadCallback
    (
        DRIVE_HANDLE h, 
        ULONGLONG ReadOffset, 
        ULONG ReadSize, 
        void* ReadBuffer, 
        ULONG *BytesRead
    );
};

A.cpp

A::A(QString filename)
{
    f = new QFile(filename);
    f.open(QFile::ReadWrite);
}

~A::A(){
    f.close();
    delete f;
}

bool A::mount()
{
    //THIS IS THE PROBLEM, CreateVirtualDrive does not take MEMBER FUNCTION POINTERS 
    //properly, instead it wants normal function pointers.
    //CreateVirtualDrive is from an external 3rd-party 
    //library, and seems to be a C function.
    g_hDrive = CreateVirtualDrive(driveLetter,DISK_SIZE,
                                  &A::OnReadCallback,
                                  &A::OnWriteCallback);
}

BOOL _stdcall A::OnWriteCallback
(
    DRIVE_HANDLE h, 
    ULONGLONG WriteOffset, 
    ULONG WriteSize, 
    const void* WriteBuffer, 
    ULONG *BytesWritten
){
    //do some work with QFile f !!
    return true;
}

BOOL _stdcall A::OnReadCallback
(
    DRIVE_HANDLE h, 
    ULONGLONG ReadOffset, 
    ULONG ReadSize, 
    void* ReadBuffer, 
    ULONG *BytesRead
){
    //do some work with QFile f !!
    return true;
}

main.cpp

#include "A.h"
int main ()
{
    A a;
    a.mount();

}

Ответы [ 3 ]

2 голосов
/ 24 января 2012

Обходной путь для этого описан в C ++ FAQ :

 class Fred {
 public:
   void memberFn();
   static void staticMemberFn();  // A static member function can usually handle it
   ...
 };

 // Wrapper function uses a global to remember the object:
 Fred* object_which_will_handle_signal;

 void Fred_memberFn_wrapper()
 {
   object_which_will_handle_signal->memberFn();
 }

 int main()
 {
   /* signal(SIGINT, Fred::memberFn); */   // Can NOT do this
   signal(SIGINT, Fred_memberFn_wrapper);  // OK
   signal(SIGINT, Fred::staticMemberFn);   // OK usually; see below
   ...
 } 
0 голосов
/ 24 января 2012

Указатели на нестатические функции-члены не могут быть преобразованы в свободные указатели на функции по стандарту C ++, так как в целом они имеют более сложную структуру, чем обычное 'void *'.

В вашем случае было бы неплохо установить глобальную (сериализованную, если у вас многопоточность) взаимно-однозначную связь между DRIVE_HANDLE и 'this' экземпляра класса A и вычислить этот указатель в OnWriteCallback / Передан OnReadCallback из дескриптора 'h'.

0 голосов
/ 24 января 2012

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

Например, в sigc ++ они имеют

signal.connect(sigc::mem_fun(this, &Class::function));

Я думаю, что QT похож.

Если такого механизма нет, вы могли бы, некрасиво, но эффективно, иметь статическую функцию, которую вы передаете в качестве обратного вызова, которая затем вызывает вашу функцию-член.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...