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

4

您好,

我的项目结构如下:

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

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

在C库“base”中,我已经声明了全局函数指针,如下所示:
在单头文件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)’转换为‘void ()’

有什么提示吗?

3个回答

8
这个问题在C++ FAQ中有解答[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
}

您需要正确设置全局变量。


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
你也可以使用静态成员函数。静态成员函数的地址可以被获取并分配给普通函数指针,因为它们没有隐式地传递this指针--在底层,这些函数的操作就像常规非成员函数一样。但是它们比非成员函数具有以下优点:
  • 静态方法仍然可以访问其类类型的任何对象的privateprotected成员。
  • 静态方法可以是privateprotected,因此可以控制对它的访问。
  • 使用静态方法可以将功能组合在类内部,使代码更加清晰。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接