Назначить метод экземпляра C ++ глобальному указателю на функцию? - PullRequest
3 голосов
/ 23 апреля 2010

Привет,

Моя структура проекта выглядит следующим образом:

\- 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 ]

7 голосов
/ 23 апреля 2010

Ответ дан в FAQ 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
}

Вы должны как-то правильно настроить глобальную переменную.

2 голосов
/ 23 апреля 2010

Вы также можете использовать функцию-член static. Адрес статической функции-члена может быть взят и назначен обычному указателю на функцию, потому что ей не передается неявно указатель this - под капотом эти функции работают так же, как обычные функции, не являющиеся членами. Но они имеют преимущества перед функциями, не являющимися членами:

  • Статический метод по-прежнему имеет доступ к private и protected членам любого объекта своего типа.
  • Статический метод может быть private или protected, поэтому доступ к нему можно контролировать.
  • Использование статического метода позволяет группировать функциональные возможности внутри класса, к которому он принадлежит.
2 голосов
/ 23 апреля 2010

Нельзя преобразовать указатель метода экземпляра в обычный указатель функции. Обходной путь - использовать другую глобальную переменную для хранения экземпляра и глобальную функцию-обертку, которая используется в качестве обратного вызова, а затем, в свою очередь, вызывает метод экземпляра:

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...