Import a DLL in QT with no .lib or .h - qt

I can't find a proper answer on the Internet, so I'm coming to you. We gave to me a .dll file and I've got a .xml file that describe every function in this .dll.
Now I want to include this .dll but every answer that I'm finding on the Internet talk about .lib and .h , is there a way to add my .dll file to my project ?
Thank you.

Here you can find what I wrote for QtSerialPort to load the symbols dynamically for udev.
This is the core principle of the code:
QLibrary myLib("mylib");
typedef void (*MyPrototype)();
MyPrototype myFunction = (MyPrototype) myLib.resolve("mysymbol");
if (myFunction)
myFunction();
If you need a "global" instance to be accessible from multiple places, you can also instantiate the QLibrary as follows:
Q_GLOBAL_STATIC(QLibrary, udevLibrary)

You can use QLibrary to call functions dynamically. The following example calls a function from a shared library at runtime:
#include <QLibrary>
#include <QDebug>
typedef int (*call_func)(int arg1, int arg2);
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QLibrary library( "dynamic_library" );
library.load();
if( !library.isLoaded() )
{
qDebug() << "Cannot load library.";
return 0;
}
call_func func = (call_func)library.resolve( "function1" );
if( func)
{
func( 1, 2 );
}
return a.exec();
}

You need to read the .xml file and generate an .h file for it. You may also wish to generate a .def file. The .def file would be used to generate an import library, needed for the linker.
If you could show a complete sample of the xml file, it should be a simple matter to leverage Qt to produce the header and definition file.

Related

QMediaPlayer - Playing BGM Continuously in Qt

I am new to Qt. I want to make a game with many different screens (e.g. Main Screen, Loading Screen...), but in a single window, switched by index in a QstackWidget. When switching to the Main Screen, it should play a background music continuously. Searching the web, I found QMediaPlayer with QMediaPlayerlist can do the trick. So I tried like this (using a basic QMainWindow to simplify the code):
QtWidgetApplication1.h
#pragma once
#include <QtWidgets/QMainWindow>
#include <QMediaPlayer>
#include <QMediaPlaylist>
class QtWidgetsApplication1 : public QMainWindow
{
Q_OBJECT
public:
QtWidgetsApplication1(QWidget *parent = Q_NULLPTR);
void playAudio();
void stopAudio();
private:
QMediaPlayer* player;
QMediaPlaylist* playList;
};
QtWidgetApplication1.cpp
#include "QtWidgetsApplication1.h"
QtWidgetsApplication1::QtWidgetsApplication1(QWidget* parent)
: QMainWindow(parent)
{
playAudio();
}
void QtWidgetsApplication1::playAudio() {
player = new QMediaPlayer();
playList = new QMediaPlaylist();
playList->addMedia(QUrl::fromLocalFile("main_theme.mp3"));
playList->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
player->setPlaylist(playList);
player->play();
}
void QtWidgetsApplication1::stopAudio() {
player->stop();
delete player;
delete playList;
player = Q_NULLPTR;
playList = Q_NULLPTR;
}
main.cpp
#include "QtWidgetsApplication1.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtWidgetsApplication1 w;
w.show();
return a.exec();
}
Error:
It only plays the audio once, and shows an error message
QObject::startTimer: Timers can only be used with threads started with
QThread
Note:
I've tried (1.) using QMediaPlayer only and detecting QMediaPlayer::endOfMedia signal, (2.) QSound with a .wav file. First approach cannot get QMediaPlayer::endOfMedia signal but get QMediaPlayer::pauseState signal, however, I still fail to replay the audio. Second approach doesn't even play the audio and shows a QEventLoop error.
Enviroment:
Windows 10
Qt 5.15.2 MSVC2019 X64
Visual Studio 2019
Instead of adding QT += multimedia in the .pro file, which the projects in VS doesn't have, I tried to include those .lib to the project settings (Refer to How to add Qt libraries to visual studio). Actually, the best way to include QtMultiMedia is: go to
Extensions (in VS) > Qt VS tools > Qt Project Settings > General > Qt Modules and select the modules you want to include. By including the right modules, the problem I have faced has gone.

Access specific object from any class

I am trying to access awesome object from another class. I declare this in main()
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QtAwesome* awesome = new QtAwesome(&app);
awesome->initFontAwesome();
app.setWindowIcon(awesome->icon( "clipboard" ));
Login w;
w.show();
return app.exec();
}
Now how do I access awesome object from Login or any another class? Is it best to initialize a class in main() if I want to access from another class?
Declaring awesome in main() makes it scoped to the main() function, and thus only visible from with main(), or functions you explicitly pass it to from main().
The simple way to achieve what you want is to use an "external variable": Put the definition and declaration outside of the main() in your main executable file:
main.cpp:
QtAwesome * awesome = new QtAwesome(&app);
int main(int argc, char *argv[]) {
awesome->do_something();
// ...
}
The above is called the defining declaration of "awesome". In other files you want to use awesome in, use the extern storage specifier:
somerandommodule.cpp:
extern QtAwesome * awesome;
void some_function() {
awesome->do_something();
}
It's important that you have exactly one "defining declaration". The linker will make all extern awesome declarations point to this one definition.
If you are the one writing the QtAwesome class, another way of doing it is keeping the single instance in the QtAwesome class. This is roughly the "singleton pattern". This just makes it easier to tell where and when initialization is happening:
qtawesome.h:
class Awesome {
private:
static Awesome * singleton;
public:
static Awesome * getInstance() {
if(!Awesome::singleton)
Awesome::singleton = new Awesome();
return Awesome::singleton;
};
};
qtawesome.cpp:
#include "awesome.h"
Awesome* Awesome::singleton = 0;
somerandommodule.cpp:
#include "awesome.h"
void some_function() {
Awesome::getInstance()->do_something();
}
You have two options
pass a pointer or reference to awesome to the Login object, e.g. as an argument to the constructor of Login
use a singleton pattern or global variable (as suggested by S.Pinkus)
A global variable or singleton increases the coupling, i.e. the Login object becomes dependent on this specific QtAwesome object to exist.
Passing an object into places of usage enables you to use a specific QtAwesome object for each usage or use the same for multiple usages, etc.
Globally accessible objects, whether global variables or singletons, often make testing more complicated, since the need for such an object is not immediately visible and all tests within the same process access the same globally accessile object, potentially resulting in tests affecting each other in unexpected ways.

Loading qm files within dynamic translation in Qt

I have an application that I want to translate the UI for Persian language. For that, I need to load qt_fa.qm and my_app_fa.qm in it. But the misfortune is, both files aren't loaded correctly. Below code always run as I expected:
QApplication app(argc, argv);
QTranslator translator;
translator.load("qt_fa"); // returns true
app.installTranslator(&translator);
translator.load("my_app_fa"); // returns true
app.installTranslator(&translator);
.
.
sometimes the qt_fa affects the application and the layout is changed to RTL and the translation of Qt used words are displayed and none of my own translations are shown.
Sometimes the my_app_fa affects the app and just my own translations are displayed.
Do have any idea about the reason?
Thanks
According to Qt Documentation with the sample code snippet you should create two objects from QTranslator
int main()
{
QApplication app(argc, argv);
QTranslator qtTranslator;
qtTranslator.load("qt_" + QLocale::system().name(),
QLibraryInfo::location(QLibraryInfo::TranslationsPath));
app.installTranslator(&qtTranslator);
QTranslator myappTranslator;
myappTranslator.load("myapp_" + QLocale::system().name());
app.installTranslator(&myappTranslator);
...
return app.exec();
}

Qt browser app with opengl-es2 strange behaviour (not working)

I have enabled opengl-es2 support in Qt/E and I wanted to make a browser app and the code is :
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QGraphicsView g;
g.setScene(new QGraphicsScene(&g));
g.scene()->setItemIndexMethod(QGraphicsScene::NoIndex);
g.setAttribute(Qt::WA_DeleteOnClose);
g.setOptimizationFlags(QGraphicsView::DontAdjustForAntialiasing);
g.setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
g.setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
g.setAlignment(Qt::AlignTop | Qt::AlignHCenter);
g.setFrameStyle(QFrame::NoFrame);
g.setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
g.setViewport(new QGLWidget());
g.showFullScreen();
QGraphicsWebView view;
view.load(QUrl("http://www.google.com"));
view.setGeometry(QRectF(0,0,800,400));
view.show();
g.scene()->addItem(&view);
a.exec();
}
I can see google page getting loaded for a fraction of second and then after it disappears.
Error log paste-bin link ==> http://pastebin.com/bgbQqd1M
Ashish,
What changes did you make for eglfs platform plug-in?
I also modified eglfs plugin to make it run on an arm board.
Two place that I changed are:
avoid call eglMakeCurrent twice, when EGLDisplay, EGLSurface(Read), EGLSurface(Draw), EGLDisplay not change --- On my board, call eglMakeCurrent twice will cause the program abort.
The problem is same as you (QGLShader::QGLShader: 'context' must be the current context or sharing with it.)
In QtOpengl library, there is a function QGLWidget* qt_gl_share_widget(), that will create a new QGLContext and set it to QPlatformGLContext.
In bool QGLShaderProgram::bind(), it will check the currentContext with the one in QGLSharedResourceGuard. QGLContext::areSharing(d->programGuard.context(), QGLContext::currentContext()).
To fix this problem.
I add the following code in qeglplatformcontext.cpp
#include <QGLContext>
class QEGLFSContext : public QGLContext
{
public:
bool chooseContext(const QGLContext* shareContext = 0)
{
QGLContext::chooseContext(shareContext); // in QGLContext, this guy is protected
}
};
void QEGLPlatformContext::makeCurrent()
{
QPlatformGLContext::makeCurrent();
QGLContext * ctx = QGLContext::fromPlatformGLContext(this);
QEGLFSContext* eglctx = (QEGLFSContext*)ctx;
static QEGLFSContext * s_ctx = eglctx;
if (s_ctx != eglctx)
{
s_ctx->chooseContext();
}
//...
}
After use these change, I can run hellogl_es2 and show the animation for show the Qt logo and bubbles well.
But I still have some problem:
QLabel, QMenu... can not show.
Do you have any idea about this problem.
I also got some idea from some guy, qws/simplegl also have these problem.

Qt quick project - how to invoke cpp function in qml file?

I' ve created quick project in Qt, selected from wizard at the begin, when Qt creator is started.
Qt creator create project. There are qmlapplicationvierwer subproject and qml files in main project. I want to add new cpp source and header files (MainMenu.cpp and MainMenu.h) to project and then invoke function from these files in main.qml file.
How I can register new type in qmlapplicationviewer and invoke function from ManiMenu ?
qmlapplicationvierwer has only few function:
QApplication app(argc, argv);
QmlApplicationViewer viewer;
viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
viewer.setMainQmlFile(QLatin1String("qml/PUTest/main.qml"));
viewer.showExpanded();
return app.exec();
and:
viewer.addImportPath(const string &path);
Better way is not create project without project wizard ?
Thanks
Normally, you use this wizard to create QML only projects.
The QmlApplication viewer is just a lightweight C++ wrapper around your QML file so a binary is generated and the QML file is loaded.
There's not much magic to do that on your own, see:
https://doc.qt.io/archives/qt-4.7/qtbinding.html
#include <QApplication>
#include <QDeclarativeView>
#include <QDeclarativeContext>
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QDeclarativeView view;
QDeclarativeContext *context = view.rootContext();
context->setContextProperty("backgroundColor",
QColor(Qt::yellow));
view.setSource(QUrl::fromLocalFile("main.qml"));
view.show();
return app.exec();
}
And with setContextProperty you can ad global QML types via cpp...
Of course you can also reuse the QmlApplicationViewer. The Mainclass QmlApplicationViewer is derived from QDeclarativeView, so you directly have access to the context in this class.
So like in the example above, it should be possible to use:
QDeclarativeContext *context = this.rootContext();
context->setContextProperty("backgroundColor", QColor(Qt::yellow));
somewhere in the QmlApplicationViewer costructor or afterwards (didn't try it for now, let me know if it doesn't work).

Resources