[CMake] Inconsistent dll linkage under Windows
Nic
cmake at fete.ch
Mon May 14 11:40:04 EDT 2007
Hello,
I'm actually using Qt with CMake and becoming pretty mad with it :)
I'm trying to compile a custom widget as a plugin for Designer, i.e as dll
for the designer.
For all tries I made for my CMakeLists I get the same result:
"warning C4273: 'staticMetaObject' : inconsistent dll linkage"
Seems that there is a problem specific to windows, for which we have to
define an export macro for dlls. I currently use QDESIGNER_WIDGET_EXPORT
macro defined by Qt.
Does anyone had similar problems ?
Thanks in advance ! nic
My configuration: Windows XP Pro 64-bit, Qt 4.2.3, Cmake 2.4.6
My code:
------------------------------------------------------------------------------
CMakelists
------------------------------------------------------------------------------
PROJECT(browserPileImagesPlugin)
cmake_minimum_required(VERSION 2.4.0)
SET(SOURCES_CPP
../code/browserPileImages.cpp
../code/browserPileImagesPlugin.cpp)
MESSAGE( STATUS ${SOURCES_CPP} )
SET(SOURCES_H
../code/browserPileImages.h
../code/browserPileImagesPlugin.h)
MESSAGE( STATUS ${SOURCES_H} )
SET(SOURCES_UI
../code/browserPileImages.ui)
MESSAGE( STATUS ${SOURCES_UI} )
# Find QT4
# attention à la casse de Qt4 !!
FIND_PACKAGE(Qt4 REQUIRED)
INCLUDE_DIRECTORIES( ${QT_QTDESIGNER_INCLUDE_DIR} )
include(${QT_USE_FILE})
#INCLUDE(${QT_INCLUDES})
# exécute uic sur les fichier .ui -> génération des .h associés
# ne pas oublier de rajouter les .h générés à add_exectuable
QT4_WRAP_UI(SOURCES_UI_H ${SOURCES_UI})
# pour la macro Q_OBJECT..
#qt4_automoc(${SOURCES_H})
QT4_WRAP_CPP( SOURCES_H_MOC ${SOURCES_H} )
# pour trouver le ui_h
INCLUDE_DIRECTORIES( ${CMAKE_CURRENT_BINARY_DIR} )
ADD_DEFINITIONS(${QT_DEFINITIONS})
ADD_DEFINITIONS(-DQT_UITOOLS)
ADD_DEFINITIONS(-DQT_PLUGIN)
ADD_DEFINITIONS(-DQT_NO_DEBUG)
ADD_DEFINITIONS(-DQT_SHARED)
ADD_LIBRARY(browserPileImagesPlugin SHARED ${SOURCES_CPP} ${SOURCES_H}
${SOURCES_UI_H} ${SOURCES_H_MOC})
TARGET_LINK_LIBRARIES(browserPileImagesPlugin ${QT_LIBRARIES} )
#install(TARGETS browserPileImagesPlugin DESTINATION
${PLUGIN_INSTALL_DIR}/plugins/designer )
------------------------------------------------------------------------------
BrowserPileImagesPlugin.h
------------------------------------------------------------------------------
#ifndef BROWSERPILEIMAGESPLUGIN_H
#define BROWSERPILEIMAGESCUSTOMWIDGETPLUGIN_H
// pour la macro QDESIGNER_WIDGET_EXPORT
#include <QtDesigner/QDesignerExportWidget>
// pour l'interface
#include <QObject>
#include <QDesignerCustomWidgetInterface>
//#include <QDesignerCustomWidgetCollectionInterface>
#include <qplugin.h>
class QDESIGNER_WIDGET_EXPORT BrowserPileImagesPlugin : public QObject,
public QDesignerCustomWidgetInterface
{
Q_OBJECT
// tell moc that the second base class is a plugin interface
Q_INTERFACES(QDesignerCustomWidgetInterface)
public:
BrowserPileImagesPlugin(QObject *parent = 0);
bool isContainer() const;
QIcon icon() const;
QString domXml() const;
QString group() const;
QString includeFile() const;
QString name() const;
QString toolTip() const;
QString whatsThis() const;
QWidget *createWidget(QWidget *parent);
};
#endif
------------------------------------------------------------------------------
BrowserPileImagesPlugin.cpp
------------------------------------------------------------------------------
#include <QtPlugin>
#include "browserPileImages.h"
#include "browserPileImagesPlugin.h"
BrowserPileImagesPlugin::BrowserPileImagesPlugin(QObject *parent) :
QObject(parent) {
//initialized = false;
}
/*
void BrowserPileImagesPlugin::initialize(QDesignerFormEditorInterface
*core ) {
if (initialized)
return;
initialized = true;
}*/
/*
bool BrowserPileImagesPlugin::isInitialized() const {
return initialized;
} */
// called by Qt Designer to create an instance of a widget class with the
given parent.
QWidget *BrowserPileImagesPlugin::createWidget(QWidget *parent)
{
return new BrowserPileImages(parent);
}
// returns the name of the widget provided by the plugin
QString BrowserPileImagesPlugin::name() const {
return "BrowserPileImages";
}
// returns the name of the widget box group this custom widget should belong
to. If the name isn't already in use,Qt Designer will create a new group for
the widget.
QString BrowserPileImagesPlugin::group() const {
return tr("Widgets perso");
}
// returns the icon to use to represent the custom widget in Qt Designer's
widget box
// assume that the plugin has an associated Qt resource file with a suitable
entry for the icon editor image.
QIcon BrowserPileImagesPlugin::icon() const {
//return QIcon();
return QIcon(":/images/myIconePlugin.png");
}
// returns the tooltip to show when the mouse hovers over the custom widget
in Qt Designer's widget box.
QString BrowserPileImagesPlugin::toolTip() const
{
return tr("Permet de parcourir une pile d'image en faisant défiler le
slider");
}
// returns the "What's This?" text for Qt Designer to display.
QString BrowserPileImagesPlugin::whatsThis() const
{
return tr("Ce widget permet de pouvoir parcourir les images d'une pile
d'image, simplement, à l'aider d'un slider.");
}
// returns true if the widget can contain other widgets; otherwise, it
returns false.
// For example, QFrame is a widget that can contain other widgets. In
general, any Qt widget can contain other widgets, but Qt Designer disallows
this when isContainer() returns false.
bool BrowserPileImagesPlugin::isContainer() const
{
return false;
}
// returns the name of the header file for the specified widget encapsulated
by the plugin
// the header file is included in the code generated by the uic tool.
QString BrowserPileImagesPlugin::includeFile() const {
return "browserPileImages.h";
}
QString BrowserPileImagesPlugin::domXml() const
{
return "<widget class=\"BrowserPileImages\"
name=\"browserPileImages\">\n"
" <property name=\"geometry\">\n"
" <rect>\n"
" <x>0</x>\n"
" <y>0</y>\n"
" <width>560</width>\n"
" <height>610</height>\n"
" </rect>\n"
" </property>\n"
"</widget>\n";
}
// make the plugin available to Qt Designer.
// The first argument is the name we want to give the plugin; the second
argument is the name of the class that implements it.
Q_EXPORT_PLUGIN2(browserPileImagesPlugin, BrowserPileImagesPlugin)
------------------------------------------------------------------------------
BrowserPileImages.h
------------------------------------------------------------------------------
#ifndef BROWSERPILEIMAGES_H
#define BROWSERPILEIMAGES_H
#include <QWidget>
// pour la macro QDESIGNER_WIDGET_EXPORT
#include <QtDesigner/QDesignerExportWidget>
#include <QList>
#include <QGraphicsPixmapItem>
#include "ui_browserPileImages.h"
// need to export class so that it can be used by the plugin
class QDESIGNER_WIDGET_EXPORT BrowserPileImages : public QWidget, private
Ui::BrowserPileImages
{
Q_OBJECT
public:
BrowserPileImages(QWidget *parent = 0);
int chargerPileImages (QString);
void afficheImage(int);
protected:
void paintEvent(QPaintEvent *event);
private slots:
void on_barreDefilement_valueChanged(int);
void on_boutonChargerPileImages_clicked();
private:
void closeEvent(QCloseEvent *event);
void sauverParametres();
void lireParametres();
QList<QGraphicsItem *> pileImages;
int numeroImageCourante;
QGraphicsScene *scene;
QGraphicsPixmapItem *pxmapItem;
};
#endif
------------------------------------------------------------------------------
BrowserPileImages.cpp
------------------------------------------------------------------------------
#include <QtGui>
#include <math.h>
#include "browserPileImages.h"
BrowserPileImages::BrowserPileImages(QWidget *parent) : QWidget(parent) {
setupUi(this);
lireParametres();
}
void BrowserPileImages::closeEvent(QCloseEvent *event)
{
// if (okToContinue()) {
sauverParametres();
/* event->accept();
} else {
event->ignore();
} */
}
// réimplémenter paintEvent
// actif quand au-dessus slider ou boutons
void BrowserPileImages::paintEvent(QPaintEvent *event)
{
}
// méthodes pour accepter un set d'images (QVector)
int BrowserPileImages::chargerPileImages (QString cheminRepertoireImages) {
//champDebugging->append("Chargement de la pile d'images..");
scene = new QGraphicsScene();
QDir repertoirePileImages(cheminRepertoireImages,"*.jpg *.tif",
QDir::Name|QDir::IgnoreCase,
QDir::Files|QDir::NoDotAndDotDot);
int nbImagesRecto = repertoirePileImages.count();
QString nbImgsRecto;
nbImgsRecto.setNum(nbImagesRecto);
//champDebugging->append("Repertoire de la pile recto:
"+repertoirePileImages.absolutePath());
//champDebugging->append("Nombre d'image: "+nbImgsRecto);
if (nbImagesRecto > 0) {
QProgressDialog progress(this);
progress.setLabelText(tr("Traitement en cours.."));
progress.setModal(true);
progress.show();
progress.setLabelText("Chargement de la pile d'images");
QString texteNombreImages;
texteNombreImages.setNum(nbImagesRecto);
QString texteNumeroImage;
for (int i=0;i<nbImagesRecto;i++) {
texteNumeroImage.setNum(i);
progress.setLabelText("Chargement de l'image
"+texteNumeroImage+"/"+texteNombreImages);
progress.setRange(0,nbImagesRecto);
progress.setValue(i);
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
if (progress.wasCanceled()) {
//champDebugging->append("Chargement interrompu par l'utilisateur !");
return nbImagesRecto;
}
//champDebugging->append(repertoirePileImages.absolutePath()+"/"+repertoirePileImages[i]);
//pxmapItemRecto =
scene->addPixmap(QPixmap("../images/"+repertoirePileImages[i]).scaled(512,512));
scene->addPixmap(QPixmap(repertoirePileImages.absolutePath()+"/"+repertoirePileImages[i]));
}
//champDebugging->append("Chargement des images terminé.");
//champDebugging->append("Récupération des items..");
pileImages = scene->items();
long double nbItems = pileImages.size();
QString nombreItems;
nombreItems.setNum((int)nbItems);
//champDebugging->append("Nombre d'items: "+nombreItems);
vuePile->setScene(scene);
for (int j=0; j< nbItems;j++) (pileImages.at(j))->hide();
barreDefilement->setMinimum(1);
barreDefilement->setMaximum(nbItems);
numeroImageCourante = floor(nbItems/2);
barreDefilement->setValue(numeroImageCourante);
(pileImages.at(numeroImageCourante))->show();
barreDefilement->setTickPosition(QSlider::TicksBelow);
}
return nbImagesRecto;
}
//Methode pour choisur l'image à afficher
//void BrowserPileImages::afficheImage(int,QVector) {}
void BrowserPileImages::on_barreDefilement_valueChanged(int) {
int numero = barreDefilement->value();
QString numStr;
numStr.setNum(numero);
//champDebugging->append("Valeur slider changée: "+numStr);
int newImageCourante = 1;
if (pileImages.size() > 0) {
newImageCourante = (barreDefilement->value()-1);
(pileImages.at(newImageCourante))->show();
(pileImages.at(numeroImageCourante))->hide();
numeroImageCourante = newImageCourante;
}
}
void BrowserPileImages::on_boutonChargerPileImages_clicked() {
QString cheminRepertoireImages = QFileDialog::getExistingDirectory(this,
tr("Spécifier le repertoire de sauvegarde de la galerie générée"),
champPathPileImages->text(),
QFileDialog::ShowDirsOnly
|
QFileDialog::DontResolveSymlinks);
if (!cheminRepertoireImages.isEmpty())
champPathPileImages->setText(cheminRepertoireImages);
chargerPileImages(cheminRepertoireImages);
}
void BrowserPileImages::sauverParametres() {
QSettings settings("Nicolas Fête, LDCS, EPFL", "LDCSViewer");
settings.setValue("pathImagesPile",champPathPileImages->text());
}
void BrowserPileImages::lireParametres(){
QSettings settings("Nicolas Fête, LDCS, EPFL", "LDCSViewer");
champPathPileImages->setText(settings.value("pathImagesPile").toString());
}
More information about the CMake
mailing list