PDA

View Full Version : Problem of including Widgets into DLL



dsedov
14th November 2008, 11:03
Hi. I am writing a software using VS2008 and QT4.3.3 with VS integration and it's structure is following:

First project is an application
Second project is a Qt Library project which produces a DLL. Now the problem I am having is that when I include DLL header file into my application compiled can't find auto generated ui_***.h file.

How should I go about including several widgets that I plan to use into a single DLL and be able to use QT Designer. If I were to write a widget from scratch without using .ui files - everything works. But the problem is that DLL compiles just fine, but the actual application, when includes DLL header (which also includes auto generated ui_***.h files) does not find those auto generated headers.

Maybe there is some other way to write a single DLL projects which includes several widgets?

janEUcitzen
14th November 2008, 11:51
HI.

I have done something the same as you do...but I made an _impl class which inluded the ui file.

the actual dll interface is defined as an interface class I have totally defined (just calls to the _impl class)...in this way I can control which elements in the widget(s) can be accessed externally.

rgds
Jan

dsedov
14th November 2008, 11:58
I am not sure what you mean by _impl class. Could you explain a little more. I am not a big C++ pro =(

janEUcitzen
14th November 2008, 13:03
I always make the dll's with one interface class.

e.g.

dll_mywidget.hpp
dll_mywidget.cpp

the class dll_mywidget are just call to another class dll_mywidget_impl

The dll_mywidget_impl class is the one that include the ui file...basically you make dll_mywidget_impl as you would make a normal widget....

and in dll_mywidget.cpp you decide which parts to make public in the dll...dont forget the class you want to make public in the dll, needs special DLL declaration (DLL_EXPORT) in order to work.

jan

dsedov
14th November 2008, 13:14
LOL I still don't get it. I think the way I understand it is that I have a dummy class which gets included into the main application and it exports other class with UI. But how do I include the base class into main application without ui header?

So far I have this:

Here the dummy class which includes the interface class (test.h) :


#ifndef FBL_GUI_H
#define FBL_GUI_H

#include "fbl_gui_global.h"
#include "test.h"
class FBL_GUI_EXPORT fbl_gui
{
public:
fbl_gui();
~fbl_gui();

private:

};

#endif // FBL_GUI_H


Then I have an interface class in the same dll project:



#ifndef TEST_H
#define TEST_H

#include <QWidget>
#include "ui_test.h"

class test : public QWidget
{
Q_OBJECT

public:
test(QWidget *parent = 0);
~test();

private:
Ui::testClass ui;
};

#endif // TEST_H


Now the problem is that if I include the base dll class it also includes the widget class. How can I skip this part but be able to access the widget and be able to create it in the main app?

spirit
14th November 2008, 13:15
Hi. I am writing a software using VS2008 and QT4.3.3 with VS integration and it's structure is following:

First project is an application
Second project is a Qt Library project which produces a DLL. Now the problem I am having is that when I include DLL header file into my application compiled can't find auto generated ui_***.h file.

How should I go about including several widgets that I plan to use into a single DLL and be able to use QT Designer. If I were to write a widget from scratch without using .ui files - everything works. But the problem is that DLL compiles just fine, but the actual application, when includes DLL header (which also includes auto generated ui_***.h files) does not find those auto generated headers.

Maybe there is some other way to write a single DLL projects which includes several widgets?

at the first you need to create h-file with the following content (e.g. myglobal.h)


#ifndef MYGLOBAL_H
#define MYGLOBAL_H

#include <QtGlobal>

#ifdef MY_LIB_STATICLIB
# undef MY_LIB_SHAREDLIB
# define MY_LIB_EXPORT
#else
# ifdef MY_LIB_MAKEDLL
# define MY_LIB_EXPORT Q_DECL_EXPORT
# else
# define MY_LIB_EXPORT Q_DECL_IMPORT
# endif
#endif

#endif//MYGLOBAL_H


then in pro-file of your lib you should add next thing


...
contains(CONFIG, staticlib) {
DEFINES += MY_LIB_STATICLIB
} else {
DEFINES += MY_LIB_SHAREDLIB
}

win32 {
DEFINES += MY_LIB_MAKEDLL
}
...


and then you must add MY_LIB_EXPORT before class name which you want to export


#include "myglobal.h"
class MY_LIB_EXPORT MyObj
{
...
};

dsedov
14th November 2008, 13:19
Yeah I know that. Thanks. The problem is that when I include DLL header in a main app it won't be able to find autogenerated files from QT Designer. Dll compiles just fine, but when main app compiles it sais : fatal error C1083: Cannot open include file: 'ui_test.h': No such file or directory

spirit
14th November 2008, 13:21
could you show us pro-file of app not lib?

dsedov
14th November 2008, 13:24
Err.. there is no .pro file. I am using VS2008 with QT integration.

spirit
14th November 2008, 13:29
ok. what do you try to do now: build a lib or build app with the lib which you are created?

dsedov
14th November 2008, 13:32
Build an app.
The lib compiles just fine. I just have problem of my app using lib headers as it cannot find autogenerated ui_***.h files.

My app has this in a header:

#include "../fbl_gui/fbl_gui.h"

This includes library header, so I will be able to use it's objects.

dsedov
15th November 2008, 09:53
So any ideas???

spirit
16th November 2008, 15:06
look at this example

Dan203
13th July 2021, 23:37
Did you ever figure this out? I'm just getting started with Qt and I'm having the exact same issue. The test file in the last post has the same error as well, so it doesn't include the fix.

Added after 9 minutes:


look at this example

FYI: This project works in Creator, but does not work in VS with the Qt plugin. In VS with Qt plugin you get an error...

fatal error C1083: Cannot open include file: 'ui_mywidget.h': No such file or directory

Added after 28 minutes:

After trying to create a similar class in Creator I noticed that it did things a bit differently. Instead of including the "ui_Dialog.h" file directly in the header it uses a pointer to a dummy namespace/class in the header, then imports the actual "ui_Dialog.h" in the cpp file.

So instead of...



#include <QDialog>
#include "ui_DialogTest.h"

class DialogTest : public QDialog
{
Q_OBJECT

public:
DialogTest(QWidget *parent = Q_NULLPTR);
~DialogTest();

private:
Ui::DialogTest ui;
};


it uses...



#include <QDialog>

namespace Ui {
class DialogTest;
}

class DialogTest : public QDialog
{
Q_OBJECT

public:
DialogTest(QWidget *parent = Q_NULLPTR);
~DialogTest();

private:
Ui::DialogTest *ui;
};


then in the cpp it uses...



#include "dialogtest.h"
#include "ui_dialogtest.h"

DialogTest::DialogTest(QWidget *parent) :
QDialog(parent),
ui(new Ui::DialogTest)
{
ui->setupUi(this);
}

DialogTest::~DialogTest()
{
delete ui;
}


I converted the auto generated class in Visual Studio to use this format and now I can use the class outside the DLL and it still works. I'm going to report this as a bug to the developers of the VS plugin and see if they'll fix it in a future version.

d_stranz
14th July 2021, 16:07
I'm going to report this as a bug to the developers of the VS plugin and see if they'll fix it in a future version.

This isn't a bug. It is simply a difference in the method of implementation.

If your QWidget-derived class uses a UI file that declares a class containing the UIC-generated UI class (in your case DialogTest, which is scoped to the Ui namespace), there are three ways to add that to the QWidget class that uses it.

First is the way your QDialog-derived DialogTest class uses it: as a pointer member of DialogTest. In this case, all you need is a forward declaration of the pointer class (Ui:: DialogTest). This is what QtCreator does.

The second way is to include Ui:: DialogClass as a member variable (not a pointer) in the DialogTest Class.

The third way is to use multiple inheritance and derive DialogTest from both QDialog and Ui:: DialogTest.

To implement these last two cases, the compiler must have access to the full definition of the Ui:: DialogTest class. This requires a #include of the ui_dialogtest.h file. A forward reference is not sufficient.

The Visual Studio plugin simply covers all cases by by #including the ui header file no matter how you use the Ui class. It isn't a bug, but it assumes that all of the code that uses the class has access to the Ui header file. This is the most common use case. It only breaks down in the rare case where the Ui class is part of a DLL -and- the QWidget-based class uses the pointer to Ui member idiom. In that case, all you have to do is move the #include statement from the .h file to the .cpp file as you have done, and replace it with a forward declaration in the header file. No big deal.

By the way if you have other resources in a DLL that you want to use in an EXE (icons, bitmaps, etc.), then you add this declaration (in main.cpp) :



int main( int argc, char * argv[] )
{
QApplication a( argc, argv );
Q_INIT_RESOURCE( MyDLL );

// ...
}


assuming your DLL is named MyDLL.dll.

Dan203
14th July 2021, 23:05
This isn't a bug. It is simply a difference in the method of implementation.

If your QWidget-derived class uses a UI file that declares a class containing the UIC-generated UI class (in your case DialogTest, which is scoped to the Ui namespace), there are three ways to add that to the QWidget class that uses it.

First is the way your QDialog-derived DialogTest class uses it: as a pointer member of DialogTest. In this case, all you need is a forward declaration of the pointer class (Ui:: DialogTest). This is what QtCreator does.

The second way is to include Ui:: DialogClass as a member variable (not a pointer) in the DialogTest Class.

The third way is to use multiple inheritance and derive DialogTest from both QDialog and Ui:: DialogTest.

To implement these last two cases, the compiler must have access to the full definition of the Ui:: DialogTest class. This requires a #include of the ui_dialogtest.h file. A forward reference is not sufficient.

The Visual Studio plugin simply covers all cases by by #including the ui header file no matter how you use the Ui class. It isn't a bug, but it assumes that all of the code that uses the class has access to the Ui header file. This is the most common use case. It only breaks down in the rare case where the Ui class is part of a DLL -and- the QWidget-based class uses the pointer to Ui member idiom. In that case, all you have to do is move the #include statement from the .h file to the .cpp file as you have done, and replace it with a forward declaration in the header file. No big deal.

By the way if you have other resources in a DLL that you want to use in an EXE (icons, bitmaps, etc.), then you add this declaration (in main.cpp) :



int main( int argc, char * argv[] )
{
QApplication a( argc, argv );
Q_INIT_RESOURCE( MyDLL );

// ...
}


assuming your DLL is named MyDLL.dll.

I started playing with it more after posting this and I noticed that there is an option in the Qt dialog wizard to do it different ways. For whatever reason I had never paid attention to that option before.

Although it's still strange that Creator uses the pointer syntax by default and the VS plugin uses the header/member variable by default. For consistency they should probably make the VS plugin use the pointer syntax as the default.