Trouble subclassing QSlider
-
Well, just tried doing that and I still get the unresolved symbol error with vtable.
Here's the new version of the class:
@
class QDSlider : public QSlider
{
Q_OBJECT
public:
explicit QDSlider():QSlider() {}
explicit QDSlider( QWidget *parent = 0 ):QSlider( parent ) {}
explicit QDSlider( Qt::Orientation orientation , QWidget *parent = 0 ):QSlider( orientation , parent ) {}
signals:
void valueChanged( double );
private slots:
void setValue( double );
};
@I added the file to the list of MOC_SRCS in CMake and let it do its thing. Still no go...
This is getting pretty frustrating...
Dave H
-
I was using the wrong macro in CMakelist.txt, so moc was no running. I now have that running and creating the .cxx files which do get compiled and linked. However, I am still getting an unresolved symbol error, but for the exact function moc was supposed to magically generate the definition for:
@
make[3]: Entering directory/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build' [ 7%] Generating ui_gsdesign.h [ 15%] Generating moc_gsdesign.cxx [ 23%] Generating moc_QDSlider.cxx [ 30%] Generating qrc_images.cxx Scanning dependencies of target gsdesigngui make[3]: Leaving directory
/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build'
make[3]: Entering directory/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build' [ 38%] Building CXX object CMakeFiles/gsdesigngui.dir/gsdesign.cpp.o [ 46%] Building CXX object CMakeFiles/gsdesigngui.dir/gsDesignGUI.cpp.o [ 53%] Building CXX object CMakeFiles/gsdesigngui.dir/gsDesignTips.cpp.o [ 61%] Building CXX object CMakeFiles/gsdesigngui.dir/GsRList.cpp.o [ 69%] Building CXX object CMakeFiles/gsdesigngui.dir/main.cpp.o [ 76%] Building CXX object CMakeFiles/gsdesigngui.dir/Rcpp.cpp.o [ 84%] Building CXX object CMakeFiles/gsdesigngui.dir/moc_gsdesign.cxx.o [ 92%] Building CXX object CMakeFiles/gsdesigngui.dir/moc_QDSlider.cxx.o [100%] Building CXX object CMakeFiles/gsdesigngui.dir/qrc_images.cxx.o Linking CXX shared library libgsdesigngui.so make[3]: Leaving directory
/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build'
[100%] Built target gsdesigngui
make[2]: Leaving directory/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build' make[2]: Entering directory
/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build'
make[3]: Entering directory/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build' Linking CXX shared library CMakeFiles/CMakeRelink.dir/libgsdesigngui.so make[3]: Leaving directory
/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build'
make[2]: Leaving directory/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build' Install the project... -- Install configuration: "" -- Installing: /home/david/workspace/GSDesignGUI/package/gsDesignExplorer/inst/libs/./libgsdesigngui.so make[1]: Leaving directory
/home/david/workspace/GSDesignGUI/package/gsDesignExplorer/explorergui-build'
** testing if installed package can be loaded
Error in dyn.load(file, DLLpath = DLLpath, ...) :
unable to load shared object '/usr/local/lib64/R/library/gsDesignExplorer/libs/libgsdesigngui.so':
/usr/local/lib64/R/library/gsDesignExplorer/libs/libgsdesigngui.so: undefined symbol: _ZN8QDSlider8setValueEd
ERROR: loading failed- removing ‘/usr/local/lib64/R/library/gsDesignExplorer’
- restoring previous ‘/usr/local/lib64/R/library/gsDesignExplorer’
@
Here is the unmangled symbol:
@
GSDesignGUI/package> c++filt _ZN8QDSlider8setValueEd
QDSlider::setValue(double)
@So, how do I get this slot and signal created?? I was told not to generate this myself, but let moc do it for me. Clearly, moc is not doing that, so how do you get it to work?!?
Here's a copy of the class as defined in the header file moc is processing:
@
class QDSlider : public QSlider
{
Q_OBJECT
public:
explicit QDSlider():QSlider() {}
explicit QDSlider( QWidget *parent = 0 ):QSlider( parent ) {}
explicit QDSlider( Qt::Orientation orientation , QWidget *parent = 0 ):QSlider( orientation , parent ) {}
signals:
void valueChanged( double );
private slots:
void setValue( double );
};
@ -
If you invoke moc manually on your header file, does it generate the needed code? If so (and I see no reason why it should not), you have a problem with your build system. I am not experienced with cmake, so I can't help you with that, but i will guarantee you that Volker is right and you must let moc generate the signals implementation for you.
-
I'm not quite convinced it's cmake yet. I just did the following:
@
moc QDSlider.h > moc_QSlider.cpp
@and then added moc_QSlider.cpp to the list of source files for compilation thinking that maybe the moc file was compiled, but not linked.
I then get the following error:
@
Linking CXX shared library libgsdesigngui.so
CMakeFiles/gsdesigngui.dir/moc_QDSlider.cxx.o: In functionQDSlider::metaObject() const': moc_QDSlider.cxx:(.text+0x0): multiple definition of
QDSlider::metaObject() const'
CMakeFiles/gsdesigngui.dir/moc_QSlider.cpp.o:moc_QSlider.cpp:(.text+0x0): first defined here
CMakeFiles/gsdesigngui.dir/moc_QDSlider.cxx.o:(.data.rel.ro+0x0): multiple definition ofQDSlider::staticMetaObject' CMakeFiles/gsdesigngui.dir/moc_QSlider.cpp.o:(.data.rel.ro+0x0): first defined here CMakeFiles/gsdesigngui.dir/moc_QDSlider.cxx.o: In function
QDSlider::qt_metacast(char const*)':
moc_QDSlider.cxx:(.text+0x20): multiple definition ofQDSlider::qt_metacast(char const*)' CMakeFiles/gsdesigngui.dir/moc_QSlider.cpp.o:moc_QSlider.cpp:(.text+0x20): first defined here CMakeFiles/gsdesigngui.dir/moc_QDSlider.cxx.o: In function
QDSlider::valueChanged(double)':
moc_QDSlider.cxx:(.text+0x70): multiple definition ofQDSlider::valueChanged(double)' CMakeFiles/gsdesigngui.dir/moc_QSlider.cpp.o:moc_QSlider.cpp:(.text+0x70): first defined here CMakeFiles/gsdesigngui.dir/moc_QDSlider.cxx.o: In function
QDSlider::qt_metacall(QMetaObject::Call, int, void**)':
moc_QDSlider.cxx:(.text+0xb0): multiple definition of `QDSlider::qt_metacall(QMetaObject::Call, int, void**)'
CMakeFiles/gsdesigngui.dir/moc_QSlider.cpp.o:moc_QSlider.cpp:(.text+0xb0): first defined here
collect2: ld returned 1 exit status
@The file moc_QSlider.cpp contained:
@
GSDesignGUI/package> cat gsDesignExplorer/src/explorergui/moc_QSlider.cpp
/****************************************************************************
** Meta object code from reading C++ file 'QDSlider.h'
**
** Created:
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.1)
**
** WARNING! All changes made in this file will be lost!
*****************************************************************************/#include "../explorergui/QDSlider.h"
#if !defined(Q_MOC_OUTPUT_REVISION)
#error "The header file 'QDSlider.h' doesn't include <QObject>."
#elif Q_MOC_OUTPUT_REVISION != 62
#error "This file was generated using the moc from 4.7.1. It"
#error "cannot be used with the include files from this version of Qt."
#error "(The moc has changed too much.)"
#endifQT_BEGIN_MOC_NAMESPACE
static const uint qt_meta_data_QDSlider[] = {// content:
5, // revision
0, // classname
0, 0, // classinfo
2, 14, // methods
0, 0, // properties
0, 0, // enums/sets
0, 0, // constructors
0, // flags
1, // signalCount// signals: signature, parameters, type, tag, flags
10, 9, 9, 9, 0x05,// slots: signature, parameters, type, tag, flags
31, 9, 9, 9, 0x08,0 // eod
};
static const char qt_meta_stringdata_QDSlider[] = {
"QDSlider\0\0valueChanged(double)\0"
"setValue(double)\0"
};const QMetaObject QDSlider::staticMetaObject = {
{ &QSlider::staticMetaObject, qt_meta_stringdata_QDSlider,
qt_meta_data_QDSlider, 0 }
};#ifdef Q_NO_DATA_RELOCATION
const QMetaObject &QDSlider::getStaticMetaObject() { return staticMetaObject; }
#endif //Q_NO_DATA_RELOCATIONconst QMetaObject *QDSlider::metaObject() const
{
return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject;
}void QDSlider::qt_metacast(const char _clname)
{
if (!_clname) return 0;
if (!strcmp(_clname, qt_meta_stringdata_QDSlider))
return static_cast<void>(const_cast< QDSlider>(this));
return QSlider::qt_metacast(_clname);
}int QDSlider::qt_metacall(QMetaObject::Call _c, int _id, void **_a)
{
_id = QSlider::qt_metacall(_c, _id, _a);
if (_id < 0)
return _id;
if (_c == QMetaObject::InvokeMetaMethod) {
switch (_id) {
case 0: valueChanged((reinterpret_cast< double()>(_a[1]))); break;
case 1: setValue((reinterpret_cast< double()>(_a[1]))); break;
default: ;
}
_id -= 2;
}
return _id;
}// SIGNAL 0
void QDSlider::valueChanged(double _t1)
{
void _a[] = { 0, const_cast<void>(reinterpret_cast<const void*>(&_t1)) };
QMetaObject::activate(this, &staticMetaObject, 0, _a);
}
QT_END_MOC_NAMESPACE
@I'll keep looking at my CMakelist.txt file, but I'm not yet convinced that this is where the problem is.
-
Ah! OK, so I implemented my QDSlider slot as follows and connected it to the QDSpinBox as follows, as well.
qdslider.h
@
#define QDSLIDER_H#include <QSlider>
class QDSlider : public QSlider
{
Q_OBJECT
public:
explicit QDSlider();
explicit QDSlider( QWidget * );
explicit QDSlider( Qt::Orientation , QWidget * );
signals:
void valueChanged( double );
private slots:
void setValue( double );
};#endif
@qdslider.cpp
@
#include "qdslider.h"QDSlider::QDSlider():QSlider() {}
QDSlider::QDSlider( QWidget *parent = 0 ):QSlider( parent ) {}
QDSlider::QDSlider( Qt::Orientation orientation , QWidget *parent = 0 ):QSlider( orientation , parent ) {}void QDSlider::setValue( double value )
{
int ivalue = value;
emit QSlider::setValue( ivalue );
}
@connect code in main program:
@
QObject::connect( ui->anlErrorDSpin , SIGNAL( valueChanged( double ) ) ,
ui->anlErrorHSlider , SLOT( setValue( double ) ) );
QObject::connect( ui->anlErrorHSlider , SIGNAL( valueChanged( double ) ) ,
ui->anlErrorDSpin , SLOT( setValue( double ) ) );
@This compiles, links, and loads. The problem is that when I run the program, I get the following error:
@
Object::connect: No such slot QSlider::setValue( double )
Object::connect: (sender name: 'anlErrorDSpin')
Object::connect: (receiver name: 'anlErrorHSlider')
Object::connect: No such signal QSlider::valueChanged( double )
Object::connect: (sender name: 'anlErrorHSlider')
Object::connect: (receiver name: 'anlErrorDSpin')
@Why is the compiled code looking for QSlider::setValue( double ) when anlErrorHSlider is defined as a QDSlider which does have a setValue( double ) defined? I tried doing the following:
@
QObject::connect( ui->anlErrorDSpin , SIGNAL( valueChanged( double ) ) ,
ui->anlErrorHSlider , SLOT( QDSlider::setValue( double ) ) );
@which resulted in the following error at run time:
@
Object::connect: No such slot QSlider::QDSlider::setValue( double )
Object::connect: (sender name: 'anlErrorDSpin')
Object::connect: (receiver name: 'anlErrorHSlider')
@What do I have to do to get the right setValue called?!?
-
Figured out why the wrong setValue was being used. the ui_xxx.h file was not being updated due to the way I was building the project. Once I deleted the offending ui_xxx.h file and pointed the include directory to the right location of the correct ui_xxx.h file, things worked better.
Now to set the signals such that updating the slider changes the spinbox and the reverse...