1

I use a 3rd party library, that does callback operations. It has a function which takes in function pointers. The problem is that I are unable to pass in pointers to functions that are members of a class.

I am using Qt and C++. The 3rd party library function seems to be a C function. The example code provided by the third party puts all code in main. This is undesirable, I need to wrap code in classes.

How can I solve this callback issue?

A.h

#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();

}
L123
  • 139
  • 4
  • 14

3 Answers3

2

There's a workaround for this described in the 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
   ...
 } 
laurent
  • 88,262
  • 77
  • 290
  • 428
0

I am not experienced with QT, but most signalling/callback systems have different methods for the member functions than standard static function pointers.

For instance, in sigc++, they have

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

I would think QT is similar.

If there is no such mechanism, you could, ugly but effective, have a static function which you pass as the callback, which then calls your member function.

Jonathan Henson
  • 8,076
  • 3
  • 28
  • 52
0

Pointers to non-static member functions cannot be casted to free function pointers by C++ standard, as, in general, they are more complex structure than plain 'void *'.

In your case, it would be a good idea to establish global (serialized, if you have multithreading) one-to-one association between DRIVE_HANDLE and 'this' of an instance of class A and evaluate to that pointer in OnWriteCallback/OnReadCallback from the handle 'h' passed in.

Arty
  • 723
  • 5
  • 10