Название: [РЕШЕНО]Проблема с Singleton
Отправлено: Hvzh от Сентябрь 22, 2014, 09:11
Доброе время суток! Пишу софт для удаленного управления фотокамерами Cannon. Использую связку EDSDK + OpenCV + Qt. Для сборки проекта - QtCreator + MSVC 2013 в качестве компайлера. Суть: переключить аппарат в режим LiveView и по картинке, показываемой в режиме реального времени ни экране компа, настраивать параметры фотокамеры. По достижении удобоваримой картинки сфоткать ее и положить на HD компа. Теперь о проблемах. EDSDK реализован в виде сишных вызовов плюс нужно зарегистрировать две Callback-функции для получения событий от фотокамеры. Сначала я быстро написал тестовый пример, состоящий из двух классов. Один отвечал за все, другой содержал только данные для настройки параметров фотокамеры. Для реализации callback'ов пришлось прибегнуть к синглтону. Вот как это выглядело в тестовом софте: QtEOS.h ... class QtEOS : public QMainWindow { Q_OBJECT
public: virtual ~QtEOS(); static QtEOS *getInstance(); QtEOS(); bool loadFile(const QString &); EdsCameraRef getCamera(){return camera;}; boolean isEDSDKLoaded = false;
//Callback's definitions static EdsError EDSCALLBACK handleObjectEvent(EdsObjectEvent event, EdsBaseRef object, EdsVoid * context); static EdsError EDSCALLBACK handleStateEvent(EdsStateEvent event, EdsUInt32 parameter, EdsVoid * context); signals: void newImage(EdsBaseRef obj); ... private: static QtEOS *m_instance; ...
Реализация: QtEOS.cpp
QtEOS::QtEOS() : QMainWindow(0) { ... m_instance = this; ... openEDSDK(); }
QtEOS* QtEOS::getInstance() { if(m_instance == 0) m_instance = new QtEOS; return m_instance; }
EdsError QtEOS::openEDSDK() { ... err = EdsSetCameraStateEventHandler(camera, kEdsStateEvent_All, handleStateEvent, NULL); ...
Реализация хендлера: EdsError EDSCALLBACK QtEOS::handleStateEvent(EdsStateEvent event, EdsUInt32 parameter, EdsVoid * context) { switch(event) { case kEdsStateEvent_CaptureError: qDebug("Event: kEdsStateEvent_CaptureError,"); case kEdsStateEvent_JobStatusChanged: qDebug("Event: kEdsStateEvent_JobStatusChanged,"); break; case kEdsStateEvent_WillSoonShutDown: qDebug("Event: kEdsStateEvent_WillSoonShutDown,"); getInstance()->EmitStatusSignal(kEdsStateEvent_WillSoonShutDown); break; default: break; } return EDS_ERR_OK; }
При таком раскладе все работало. Теперь я решил для нормального проекта разобрать эту кашу, раскидав различный функционал по различным классам. В частности, в отдельный класс решил выделить все, что связано с удаленной работой с фотокамерой. В итоге получился такой класс: CameraController.h
class CameraController : public QObject { Q_OBJECT
public: virtual ~CameraController(); static CameraController *getInstance(); CameraController(QObject *parent = 0); static EdsError EDSCALLBACK handleObjectEvent(EdsObjectEvent event, EdsBaseRef object, EdsVoid * context); static EdsError EDSCALLBACK handleStateEvent(EdsStateEvent event, EdsUInt32 parameter, EdsVoid * context); signals: void newImage(EdsBaseRef obj); ...
Реализация: CameraController.cpp
CameraController::CameraController(QObject *parent) : QObject(parent) { m_instance = this; }
CameraController* CameraController::getInstance() { if(m_instance == 0) m_instance = new CameraController; return m_instance; } ... EdsError EDSCALLBACK CameraController::handleStateEvent(EdsStateEvent event, EdsUInt32 parameter, EdsVoid * context) { switch(event) { case kEdsStateEvent_CaptureError: qDebug("Event: kEdsStateEvent_CaptureError,");
case kEdsStateEvent_JobStatusChanged: qDebug("Event: kEdsStateEvent_JobStatusChanged,"); break; case kEdsStateEvent_WillSoonShutDown: qDebug("Event: kEdsStateEvent_WillSoonShutDown,"); getInstance()->EmitStatusSignal(kEdsStateEvent_WillSoonShutDown); break; default: break; } return EDS_ERR_OK; }
Теперь при компиляции получаю такую ошибку: cameracontroller.obj:-1: error: LNK2001: неразрешенный внешний символ ""private: static class CameraController * CameraController::m_instance" (?m_instance@CameraController@@0PAV1@A)"
Название: Re: Проблема с Singleton
Отправлено: alex312 от Сентябрь 22, 2014, 09:34
http://www.c-cpp.ru/books/staticheskie-chleny-klassa
Название: Re: Проблема с Singleton
Отправлено: StLynx от Сентябрь 22, 2014, 09:37
Добавте CameraController * CameraController ::m_instance = 0; в реализацию.
Название: Re: Проблема с Singleton
Отправлено: Hvzh от Сентябрь 22, 2014, 09:58
alex312, StLynx, Спасибо!
Название: Re: Проблема с Singleton
Отправлено: Hvzh от Сентябрь 26, 2014, 09:42
Реанимирую данную тему, поскольку возникла еще одна проблема. В коде две callback - функции: EdsError EDSCALLBACK CameraController::handleStateEvent(EdsStateEvent event, EdsUInt32 parameter, EdsVoid * context) { switch(event) { case kEdsStateEvent_CaptureError: qDebug("Event: kEdsStateEvent_CaptureError");
case kEdsStateEvent_JobStatusChanged: qDebug("Event: kEdsStateEvent_JobStatusChanged"); break; case kEdsStateEvent_WillSoonShutDown: qDebug("Event: kEdsStateEvent_WillSoonShutDown"); getInstance()->EmitStatusSignal(kEdsStateEvent_WillSoonShutDown); break; case kEdsStateEvent_Shutdown: qDebug("Event: kEdsStateEvent_Shutdown"); getInstance()->EmitStatusSignal(kEdsStateEvent_Shutdown); break; default: break; }
qDebug("Event code: 0x%X.\n", (int)event);
return EDS_ERR_OK; }
и EdsError EDSCALLBACK CameraController::handleObjectEvent(EdsObjectEvent event, EdsBaseRef object, EdsVoid * context) { if(event == kEdsObjectEvent_DirItemCreated || event == kEdsObjectEvent_DirItemRequestTransfer || event == kEdsObjectEvent_DirItemRequestTransferDT) { getInstance()->EmitSignal(object); }
return EDS_ERR_OK; }
Обе посылают сигналы посредством, соответственно, getInstance()->EmitStatusSignal и getInstance()->EmitSignal. Однако в случае первой callback - функции сигнал не шлется почему-то... Функции выглядят следующим образом: void CameraController::EmitStatusSignal(long status) { switch (status) { case kEdsStateEvent_WillSoonShutDown: sendShutdownTimer(); break; case kEdsStateEvent_Shutdown: qDebug() << "CameraController::takeStatus before emit"; emit cameraOff(); qDebug() << "CameraController::takeStatus after emit"; break; default: break; } } void CameraController::EmitSignal(EdsBaseRef obj) { emit newImage(obj); }
В итоге сигнал newImage нормально ловится классом, который ответственен за интерфейс пользователя, а сигнал cameraOff до него не доходит. Вот вывод с консоли: Event: kEdsStateEvent_Shutdown CameraController::takeStatus before emit CameraController::takeStatus after emit Event code: 0x301.
Название: [РЕШЕНО] Проблема с Singleton
Отправлено: Hvzh от Сентябрь 26, 2014, 13:12
Решилось путем отказа от синглтона
|