2010-04-23 87 views
3

問候,將C++實例方法分配給全局函數指針?

我的項目結構如下:

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

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

在C庫 '基地',我已經宣佈全球函數指針:

在singleheader文件

callbacks.h

#ifndef CALLBACKS_H_ 
#define CALLBACKS_H_ 

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

#endif /* CALLBACKS_H_ */ 

in single 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: 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 ()()’

任何提示?

回答

7

這在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 
} 

你必須以某種方式設置全局變量正常。

+0

非常感謝馬修,那工作 – 2010-04-23 02:29:40

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

非常感謝,這真的有幫助 – 2010-04-23 02:29:15

2

您也可以使用一個static成員函數。靜態成員函數的地址可以被分配給一個常規的函數指針,因爲沒有this指針被隱式地傳遞給它 - 在引擎蓋下,這些函數就像普通的非成員函數一樣操作。但是它們具有優於非成員函數的優點:

  • 靜態方法仍然可以訪問它的類類型的任何對象的privateprotected成員。
  • 靜態方法可以是privateprotected,因此可以控制對其的訪問。
  • 使用靜態方法,您可以在該類所屬的位置對其進行分組。