[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