Solved How can I use a DLL, in VS, without needing to load the moc files from the DLL?
-
Dear Koahnig
If indeed I do, and my DLL works correctly. That is, I have a DLL called AeCreator.dll, and an application called AeCretor_test.exeIn the AeCreator_text.exe application, use the AeCreator DLL, for this in VS, for the AeCreator_text.exe project, I configured it as follows;
(QTDIR) \ include \ QtCui \ $ (QTDIR) \ include (QTDIR) \ include (QTDIR) \ include () Include \ QtWidgets; .. \ AeCreator; .. \ AeCreator \ GeneratedFiles \ $ (ConfigurationName);% (AdditionalIncludeDirectories)
Preprocessor:
UNICODE; WIN64; QT_DLL; QT_NO_DEBUG; NDEBUG; QT_CORE_LIB; QT_GUI_LIB; QT_WIDGETS_LIB; AECREATOR_LIB;% (PreprocessorDefinitions)Linker:
Qtmaind.lib; Qt5Cored.lib; Qt5Guid.lib; Qt5Widgetsd.lib; AeCreatord.lib;% (AdditionalDependencies)But for it to work properly, I must manually load the moc _ *. Cpp files from AeCreator.dll, in the AeCreator_text project, into the GeneratedFiles folder.
In this way, the application runs correctly, but this work is very tedious, when you have a big projects with many DLLs, and in addition you have to remember that moc files correspond to those DLLs, and load them all manually.
The query is, is there any way in VS, that when declaring the use of those DLLs, the moc files are located by the compiler without having to indicate them in the project manually?
Thank you.
-
If the moc files belonging to the DLL project, in my case AeCreator.dll, are not loaded manually in the AeCreator_test.exe project, in the GeneratedFiles folder, the following error occurs;
1>main.obj : error LNK2001: sÝmbolo externo "public: static struct QMetaObject const AeBaseCreatorWidget::staticMetaObject" (?staticMetaObject@AeBaseCreatorWidget@@2UQMetaObject@@B) sin resolver
1>main.obj : error LNK2001: sÝmbolo externo "public: static struct QMetaObject const AeBaseCreatorMenu::staticMetaObject" (?staticMetaObject@AeBaseCreatorMenu@@2UQMetaObject@@B) sin resolver
1>C:\Programacion\Lib\src\AeCreator\x64\Debug\AeCreator_Text01.exe : fatal error LNK1120: 2 externos sin resolverBecause the AeCreator_test.exe project is not currently loading the project's moc files from the AeCreator.dll DLL.
Is there an automatic way to indicate the necessary moc files belonging to the project of a dll, without having to load them manually? -
@AEROLASER_THA said in How can I use a DLL, in VS, without needing to load the moc files from the DLL?:
Is there an automatic way to indicate the necessary moc files belonging to the project of a dll, without having to load them manually?
As @koahnig hinted, you don't need to have anything moc related from the dll in the app. That's one of the points of using a dll. If you get that linker error, then you should search the problem in the way you build the library, the error basically means the mocs weren't compiled into the dll (or rather the meta information wasn't exported from it).
Have you exported the classes from said dll, which is usually the problem when you get such errors?
-
Dear Kshegunov;
If I have actually declared the export of DLL classes#ifndef AECREATOR_GLOBAL_H
#define AECREATOR_GLOBAL_H#include <QtCore/qglobal.h>
#ifdef AECREATOR_LIB
define AECREATOR_EXPORT Q_DECL_EXPORT
#else
define AECREATOR_EXPORT Q_DECL_IMPORT
#endif
#endif // AECREATOR_GLOBAL_H#include "aecreator_global.h"
class AECREATOR_EXPORT AeBaseCreatorMenu : public QObject -
@AEROLASER_THA said in How can I use a DLL, in VS, without needing to load the moc files from the DLL?:
class AECREATOR_EXPORT AeBaseCreatorMenu : public QObject
And do you have the
Q_OBJECT
macro, I can't tell from your snippet? -
YES
#ifndef AEBASECREATORMENU_H #define AEBASECREATORMENU_H #include "aecreator_global.h" #include <QObject> #include <QString> #include <QVariant> class QMenu; class AECREATOR_EXPORT AeBaseCreatorMenu : public QObject { Q_OBJECT public: explicit AeBaseCreatorMenu(const QString &creatorName, QObject *parent = 0); virtual ~AeBaseCreatorMenu(); virtual QMenu* createMenu(QWidget *parent = 0) = 0; //GET// QString getName() const; QVariant::Type getType() const; QString getPropertyName() const; //SET// void setType(const QVariant::Type &type); void setPropertyName(const QString &propertyName); private: Q_DISABLE_COPY(AeBaseCreatorMenu); //MEMBERS// QVariant::Type type; QString name; QString propertyName; }; #endif // AEBASECREATORMENU_H
[Added code tags ~kshegunov]
-
@AEROLASER_THA
You shouldn't pass theAECREATOR_LIB
macro when building the application. And bear in mind you can't create objects of typeAeBaseCreatorMenu
as the class is abstract. -
#ifndef AECREATORMENU_H #define AECREATORMENU_H #include "aebasecreatormenu.h" template <class T> class AECREATOR_EXPORT AeCreatorMenu : public AeBaseCreatorMenu { public: explicit AeCreatorMenu(const QString &creatorName, QObject *parent = 0) : AeBaseCreatorMenu(creatorName, parent){}; ~AeCreatorMenu(){}; QMenu* createMenu(QWidget *parent = 0) { return static_cast<QMenu*>(new T(parent)); } private: Q_DISABLE_COPY(AeCreatorMenu); }; #endif // AECREATORMENU_H
[Added code tags ~kshegunov]
-
Hi
You are trying to export a template which wont work as class T is not yet known.
As far as I know, you can only export an instantiation where T is set to a type. -
@AEROLASER_THA
Dear Kshegunov;
The problem is with any class, regardless of whether it is abstract or not. With any simple project and class.If I am actually declaring AECREATOR_LIB, in the project AeCreator_test.exe
Preprocessor:
UNICODE; WIN64; QT_DLL; QT_NO_DEBUG; NDEBUG; QT_CORE_LIB; QT_GUI_LIB; QT_WIDGETS_LIB; AECREATOR_LIB;% (PreprocessorDefinitions) -
@AEROLASER_THA
Hi
Did you try something simple like
https://wiki.qt.io/How_to_create_a_library_with_Qt_and_use_it_in_an_applicationIt shows the step both for the DLL and for the host app.
-
@AEROLASER_THA said in How can I use a DLL, in VS, without needing to load the moc files from the DLL?:
If I am actually declaring AECREATOR_LIB, in the project AeCreator_test.exe
Which I said you shouldn't! You should define that only when building the library, not when using the library, otherwise it will not expand to
__declspec(dllimport)
which is mandatory on windows. -
//DLL test
#include "test_global.h" #include <QtWidgets/QWidget> class TEST_EXPORT Widget : public QWidget { Q_OBJECT public: Widget(); };
//test_global.h
#include <QtCore/qglobal.h> #ifndef QT_STATIC # if defined(TEST_LIB) # define TEST_EXPORT Q_DECL_EXPORT # else # define TEST_EXPORT Q_DECL_IMPORT # endif #else # define TEST_EXPORT #endif //test.cpp #include "test.h" Widget::Widget() { }
//PROJECT
#include <QtWidgets/QApplication> #include "test.h" int main(int argc, char *argv[]) { QApplication a(argc, argv); Widget w; w.resize(100, 100); w.show(); return a.exec(); }
//CONFIFGURATION
Additional Inclusion Directories;
.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;..\test;..\test\GeneratedFiles$(ConfigurationName);%(AdditionalIncludeDirectories)Preprocessor;
UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;TEST_LIB;%(PreprocessorDefinitions)Directory of additional libraries;
$(QTDIR)\lib;$(SolutionDir)$(Platform)$(Configuration);%(AdditionalLibraryDirectories)
Linker;
qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;test.lib;%(AdditionalDependencies)If I do not load the moc_test.cpp file generated with the DLL, the following error occurs in the exe project manually;
main.obj : error LNK2001: símbolo externo "public: static struct QMetaObject const Widget::staticMetaObject" (?staticMetaObject@Widget@@2UQMetaObject@@B) sin resolver
1>c:\Users\therrera\documents\visual studio 2015\Projects\test\x64\Debug\Project.exe : fatal error LNK1120: 1 externos sin resolverIf you manually load the m_test.cpp file, in the project, in the GeneratedFiles folder, it runs perfectly.
It is as if the moc code was not contained in the DLL[Added code tags ~kshegunov]
-
Hi
It sounds like
if defined(TEST_LIB)
define TEST_EXPORT Q_DECL_EXPORT
is active when you build the app ?In sample the key points are
TEMPLATE = lib <<<
DEFINES += TEST<<<
for the LIB, not app.So how are you controlling the TEST_LIB when building the lib and the app ?
for the app, TEST_LIB is not to be defined. -
@mrjj
Yes, is active//DLL
Preprocessor;
UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;TEST_LIB;%(PreprocessorDefinitions)
Linker;
qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;%(AdditionalDependencies)//PROJECT
Preprocessor;
UNICODE;WIN32;WIN64;QT_DLL;QT_CORE_LIB;QT_GUI_LIB;QT_WIDGETS_LIB;TEST_LIB;%(PreprocessorDefinitions)
Linker;
qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgetsd.lib;test.lib;%(AdditionalDependencies)But it only runs correctly, if in the project manually load the moc_test.cpp
-
So you are 100% sure that its Q_DECL_IMPORT when building the app and
Q_DECL_EXPORT when building the LIB/DLL ?
Sorry I cannot see it from your output.
Both seems to say TEST_LIB; which is wrong.
Only
//DLL
Preprocessor;
should have it. -
TEST_LIB is declared in both DLL and Project
If I do not declare in Project, in preprocessor, it gives me error.
moc_test.cpp
1>..\test\GeneratedFiles\Debug\moc_test.cpp(56): warning C4273: 'Widget::qt_static_metacall': vinculación de DLL incoherente
1> c:\users\therrera\documents\visual studio 2015\projects\test\test\generatedfiles\debug../../test.h(10): note: vea la definición anterior de 'qt_static_metacall'
1>..\test\GeneratedFiles\Debug\moc_test.cpp(63): warning C4273: 'staticMetaObject': vinculación de DLL incoherente
1> c:\users\therrera\documents\visual studio 2015\projects\test\test\generatedfiles\debug../../test.h(10): note: vea la definición anterior de 'public: static QMetaObject const Widget::staticMetaObject'
1>..\test\GeneratedFiles\Debug\moc_test.cpp(63): error C2491: 'Widget::staticMetaObject': definición de miembro de datos estático dllimport no permitida
1>..\test\GeneratedFiles\Debug\moc_test.cpp(70): warning C4273: 'Widget::metaObject': vinculación de DLL incoherente
1> c:\users\therrera\documents\visual studio 2015\projects\test\test\generatedfiles\debug../../test.h(10): note: vea la definición anterior de 'metaObject'
1>..\test\GeneratedFiles\Debug\moc_test.cpp(75): warning C4273: 'Widget::qt_metacast': vinculación de DLL incoherente
1> c:\users\therrera\documents\visual studio 2015\projects\test\test\generatedfiles\debug../../test.h(10): note: vea la definición anterior de 'qt_metacast'
1>..\test\GeneratedFiles\Debug\moc_test.cpp(83): warning C4273: 'Widget::qt_metacall': vinculación de DLL incoherente
1> c:\users\therrera\documents\visual studio 2015\projects\test\test\generatedfiles\debug../../test.h(10): note: vea la definición anterior de 'qt_metacall'
1> main.cpp -
@AEROLASER_THA
hmm. ok. im going to try the small test project and see.
You added a UI files also ? -
In this example, I am not using ui files
-
Dear All;
I finally found the problem.
I was creating a DLL project, and within this project I created the EXE project.
When declaring the path of the inclusion directories of the EXE project, it was not correctly including the address of the path where the libAnd indeed my initial confusion was due to the fact of trying to export a template as a class T that is not known.
Excuse me
.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;..\test;..\test\GeneratedFiles$(ConfigurationName);C:\Users\therrera\Documents\Visual Studio 2015\Projects\test\x64\Debug;C:\Users\therrera\Documents\Visual Studio 2015\Projects\test\test\x64\Debug;C:\Users\therrera\Documents\Visual Studio 2015\Projects\test\test\GeneratedFiles\Debug;C:\Users\therrera\Documents\Visual Studio 2015\Projects\test\test;%(AdditionalIncludeDirectories)