Note: It didn't compile for me at first (code provided is not complete), so I had to make some changes, hope I've preserved the functionality you're aiming to.
First, some comments about creating/using DLLs:
__declspec(dllexport)
is only necessary when you want to import symbols, as with create
. As you are creating the object from within the DLL, the class itself doesn't have to be exported.
- If you define your class in the way you do, the compiler will wait for the definition too, which happens to be in a DLL (and that DLL is not providing a .lib with the definitions table). It means that the code won't compile.
- To fix that you can either:
- you export the class too, the compiler generates a .lib file (at least in VS) and link your application with it, which means that all the
QLibrary
code is not necessary.
- you convert your class in a pure virtual class (only public members are required here), derive it to an inner class of the DLL (the implementation class) and use
create
as a factory (it creates an instance of the implementation class).
As you seem to aim to use the QLibrary
, maybe to make a plugin-like feature, I'm showing you the second solution, if you prefer the other one, just let me know and I'll extend the answer to cover that.
Solution based on pure virtual class
dll.h, public header file, to expose the design of the class
#ifndef DIVFIXTURE_H
#define DIVFIXTURE_H
#include<QObject>
#include<QVariant>
class DivFixture : public QObject {
public:
virtual ~DivFixture() {}
virtual Q_INVOKABLE void setNumerator(QVariant num) = 0;
virtual Q_INVOKABLE void setDenominator(QVariant denom) = 0;
virtual Q_INVOKABLE QVariant quotient() = 0;
};
#endif
dll_impl.h, not intended to be used outside the DLL, stores the actual
#ifndef DIVFIXTURE_IMPL_H
#define DIVFIXTURE_IMPL_H
#include "dll.h"
class DivFixture_Impl : public DivFixture {
public:
DivFixture_Impl();
virtual ~DivFixture_Impl() {}
virtual Q_INVOKABLE void setNumerator(QVariant num) override;
virtual Q_INVOKABLE void setDenominator(QVariant denom) override;
virtual Q_INVOKABLE QVariant quotient() override;
protected:
double numerator, denominator;
};
#endif
dll.cpp, actual implementation
#include "dll_impl.h"
DivFixture_Impl::DivFixture_Impl() : numerator(0.0), denominator(1.0) {}
void DivFixture_Impl::setNumerator(QVariant num)
{
numerator = num.toDouble();
}
void DivFixture_Impl::setDenominator(QVariant denom)
{
denominator = denom.toDouble();
}
QVariant DivFixture_Impl::quotient()
{
QVariant ret;
ret = numerator / denominator;
return ret;
}
// non-class function to return pointer to class
extern "C" __declspec(dllexport) DivFixture* create()
{
return new DivFixture_Impl();
}
main.cpp
#include <QtCore>
#include "../dll/dll.h"
int main()
{
QLibrary library("dll.dll");
if (!library.load()) {
qDebug() << library.errorString();
return 0;
}
qDebug() << "library loaded";
typedef DivFixture * (*MyPrototype)();
auto myFunction = (MyPrototype)library.resolve("create");
qDebug() << myFunction;
DivFixture* r1 = nullptr;
if (myFunction)
r1 = myFunction();
if (r1 != nullptr) {
r1->setDenominator(2.0);
r1->setNumerator(10.0);
auto r = r1->quotient();
qDebug() << r.toDouble();
} else {
qDebug() << "r1 not created!";
}
return 0;
}
Additional notes
Regarding the crash, the third line in the code below will be executed regardless myFunction
is null or not, so the crash may actually come from the fact that r1
is not initialized.
if (myFunction)
r1=myFunction();
r1->quotient();
Be careful about incongruences between indentation and actual code blocks. Use braces here:
if (myFunction) {
r1=myFunction();
r1->quotient();
}
or check that r1
is not null before using it:
if (myFunction)
r1=myFunction();
if (r1 != nullptr)
r1->quotient();
Also, probably it is just a typo but you check for if (myFunction)
but in the next line call Function
instead of myFunction
. The same for the header file names. Be careful about these things when posting code, since they make very difficult to reproduce your problem, thus you probably won't get an answer or an adequate one.
Finally, and as a small note, unless you want to insert an additional blank line, qDebug
already adds a line break at the end, so it is not necessary to use the endl
.