开发者

Assign C++ instance method to a global-function-pointer?

开发者 https://www.devze.com 2022-12-28 01:56 出处:网络
Greetings, My project structure is as follows: \\- base(C static library) callbacks.h callbacks.c paint_node.c

Greetings,

My project structure is as follows:

\- base  (C static library)
     callbacks.h
     callbacks.c
     paint_node.c
     . 
     .
     * libBase.a

\-app (C++ application)
     main.cpp

In C library 'base' , I have declared global-function-pointer as:

in singleheader file

callbacks.h

#ifndef CALLBACKS_H_
#define CALLBACKS_H_

extern void (*putPixelCallBack)();
extern void (*putImageCallBack)();

#endif /* CALLBACKS_H_ */

in single C file they are initialized as

callbacks.c

#include "callbacks.h"
void (*putPixelCallBack)();
void (*putImageCallBack)();

Other C files access this callback-functions as:

paint_node.c

#include "callbacks.h"
void paint_node(node *开发者_高级运维node,int index){

  //Call callbackfunction
  .
  .

  putPixelCallBack(node->x,node->y,index);
}

I compile these C files and generate a static library 'libBase.a'

Then in C++ application,

I want to assign C++ instance method to this global function-pointer:

I did something like follows :

in Sacm.cpp file

#include "Sacm.h"

extern void (*putPixelCallBack)();
extern void (*putImageCallBack)();

void Sacm::doDetection()
{
  putPixelCallBack=(void(*)())&paintPixel;
  //call somefunctions in 'libBase' C library

}

void Sacm::paintPixel(int x,int y,int index)
{
 qpainter.begin(this);
 qpainter.drawPoint(x,y);
 qpainter.end();
}

But when compiling it gives the error:

sacmtest.cpp: In member function ‘void Sacm::doDetection()’: sacmtest.cpp:113: error: ISO C++ forbids taking the address of an unqualified or parenthesized non-static member function to form a pointer to member function. Say ‘&Sacm::paintPixel’ sacmtest.cpp:113: error: converting from ‘void (Sacm::)(int, int, int)’ to ‘void ()()’

Any tips?


This is answered in the C++ FAQ, [1]. This doesn't work, because the pointer isn't associated with a particular object instance. The solution is given there too, create a global function that uses a particular object:

 Sacm* sacm_global;

 void sacm_global_paintPixel(int x,int y,int index)
 {
   sacm_global->paintPixel(x, y, index);
 }

void Sacm::doDetection()
{
  putPixelCallBack = &sacm_global_paintPixel;
  //call somefunctions in 'libBase' C library
}

You have to somehow setup the global variable properly.


You cannot convert an instance method pointer to a normal function pointer. A workaround is to use another global variable to hold the instance and a global wrapper function that is used as the callback and then in turn calls the instance method:

Sacm *callbackSacm;

extern "C"  // since it sounds like it's called from a C library
void call_paintPixel(int x, int y, int index) {
   callbackSacm->paintPixel(x, y, index);
}

void Sacm::doDetection() {
   callbackSacm = this;
   putPixelCallBack = call_paintPixel;
}


You can alternatively use a static member function. The address of a static member function can be taken and assigned to a regular function pointer, because no this pointer is implicitly passed to it -- under the hood, these functions operate just like regular non-member functions. But they have advantages over non-member functions:

  • A static method still has access to the private and protected members of any object of its class type.
  • A static method can be private or protected so access to it can be controlled.
  • Using a static method lets you and group functionality inside the class, where it belongs.
0

精彩评论

暂无评论...
验证码 换一张
取 消