Я могу создать экземпляр класса в Qt main.cpp, но мое приложение терпит крах при попытке получить доступ к функции-члену класса DLL.
Как мне это сделать?
Если это мой dll.h
#ifndef DIVFIXTURE_H
#define DIVFIXTURE_H
#include<QObject>
#include<QVariant>
class __declspec(dllexport) DivFixture : public QObject
{
Q_OBJECT
public:
Q_INVOKABLE DivFixture();
Q_INVOKABLE void setNumerator(QVariant num);
Q_INVOKABLE void setDenominator(QVariant denom);
Q_INVOKABLE QVariant quotient();
private:
double numerator, denominator;
};
#endif
Это мой dll.cpp
#include "testfixture.h"
DivFixture::DivFixture(){}
void DivFixture::setNumerator(QVariant num)
{
numerator=num.toDouble();
}
void DivFixture::setDenominator(QVariant denom)
{
denominator=denom.toDouble();
}
QVariant DivFixture::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();
}
Это main.cpp моего приложения Qt, куда я импортирую библиотеку DLL
QLibrary library(("C:\\somepath\\testFixture.dll");
if (!library.load())
qDebug() << library.errorString() << endl;
if (library.load())
qDebug() << "library loaded" << endl;
DivFixture *r1=NULL;
typedef DivFixture* (*MyPrototype)();
auto myFunction = (MyPrototype)library.resolve("create");
qDebug()<<myFunction;
if (myFunction)
r1=Function(); // able to create instance of DivFixture
r1->quotient(); //I'm not able to access class member function
Почему я не могу получить доступ к функции класса quotient()
используя экземпляр класса? Программа падает на этой линии r1->quotient();
, Вместо создания прототипа функции в DLL, как typedef DivFixture* (*MyPrototype)();
Могу ли я создать прототип моего класса DivFixture
получить доступ к его функциям-членам?
Примечание. Сначала он не компилировался (предоставленный код не завершен), поэтому мне пришлось внести некоторые изменения, надеюсь, я сохранил ту функциональность, к которой вы стремитесь.
Сначала несколько комментариев о создании / использовании DLL:
__declspec(dllexport)
необходимо только тогда, когда вы хотите импортировать символы, как с create
, Поскольку вы создаете объект из библиотеки DLL, сам класс не нужно экспортировать.QLibrary
код не нужен.create
как фабрика (это создает экземпляр класса реализации).Как вы, кажется, стремитесь использовать QLibrary
Может быть, чтобы сделать плагин-подобную функцию, я покажу вам второе решение, если вы предпочитаете другое, просто дайте мне знать, и я расширю ответ, чтобы охватить это.
Решение на основе чисто виртуального класса
dll.h, публичный заголовочный файл, чтобы раскрыть дизайн класса
#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, не предназначенный для использования вне DLL, хранит фактические
#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, фактическая реализация
#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;
}
Дополнительные примечания
Что касается сбоя, третья строка в коде ниже будет выполняться независимо myFunction
является нулевым или нет, так что авария может быть вызвана тем фактом, что r1
не инициализируется.
if (myFunction)
r1=myFunction();
r1->quotient();
Будьте осторожны с несоответствиями между отступом и фактическими блоками кода. Используйте здесь фигурные скобки:
if (myFunction) {
r1=myFunction();
r1->quotient();
}
или проверь что r1
не является нулевым, прежде чем использовать его:
if (myFunction)
r1=myFunction();
if (r1 != nullptr)
r1->quotient();
Кроме того, вероятно, это просто опечатка, но вы проверяете if (myFunction)
но в следующей строке вызов Function
вместо myFunction
, То же самое для имен файлов заголовков. Будьте осторожны с этими вещами при публикации кода, поскольку они очень затрудняют воспроизведение вашей проблемы, поэтому вы, вероятно, не получите ответ или адекватный.
Наконец, и в качестве небольшой заметки, если вы не хотите вставить дополнительную пустую строку, qDebug
уже добавляет разрыв строки в конце, поэтому нет необходимости использовать endl
,
Других решений пока нет …