将C ++实例方法分配给全局函数指针?

时间:2010-04-23 02:07:50

标签: c++ c pointers global-variables function-pointers

问候,

我的项目结构如下:

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

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

在C库'base'中,我将global-function-pointer声明为:

单头文件中的

callbacks.h

#ifndef CALLBACKS_H_
#define CALLBACKS_H_

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

#endif /* CALLBACKS_H_ */

在单个C文件中,它们被初始化为

的callbacks.c

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

其他C文件访问此回调函数:

paint_node.c

#include "callbacks.h"
void paint_node(node *node,int index){

  //Call callbackfunction
  .
  .

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

我编译这些C文件并生成一个静态库'libBase.a'

然后在C ++应用程序中,

我想将C ++实例方法分配给这个全局函数指针:

我做了类似的事情:

在Sacm.cpp文件中

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

但是在编译它时会出现错误:

  

sacmtest.cpp:在成员函数'void中   SACM :: doDetection()”:   sacmtest.cpp:113:错误:ISO C ++   禁止取得地址   不合格或括号内的   非静态成员函数形成一个   指向成员函数的指针。说   '& Sacm :: paintPixel'sacmtest.cpp:113:   错误:从'void转换   (Sacm :: )(int,int,int)'to'void   ()()”

任何提示?

3 个答案:

答案 0 :(得分:7)

这在C ++常见问题解答[1]中得到了解答。这不起作用,因为指针不与特定对象实例相关联。解决方案也在那里,创建一个使用特定对象的全局函数:

 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
}

你必须以某种方式正确设置全局变量。

答案 1 :(得分:2)

您无法将实例方法指针转换为普通函数指针。解决方法是使用另一个全局变量来保存实例和一个用作回调的全局包装函数,然后调用实例方法:

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;
}

答案 2 :(得分:2)

您也可以使用static成员函数。可以获取静态成员函数的地址并将其分配给常规函数指针,因为没有this指针隐式传递给它 - 在引擎盖下,这些函数就像常规的非成员函数一样运行。但它们优于非成员函数:

  • 静态方法仍然可以访问其类类型的任何对象的privateprotected成员。
  • 静态方法可以是privateprotected,因此可以控制对它的访问。
  • 使用静态方法可以在类中包含它所属的功能。