Доброе время суток!
Пишу софт для удаленного управления фотокамерами 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)"