Доступ к функциям-членам класса C ++ библиотеки DLL в Qt

Я могу создать экземпляр класса в 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 получить доступ к его функциям-членам?

-1

Решение

Примечание. Сначала он не компилировался (предоставленный код не завершен), поэтому мне пришлось внести некоторые изменения, надеюсь, я сохранил ту функциональность, к которой вы стремитесь.

Сначала несколько комментариев о создании / использовании DLL:

  1. __declspec(dllexport) необходимо только тогда, когда вы хотите импортировать символы, как с create, Поскольку вы создаете объект из библиотеки DLL, сам класс не нужно экспортировать.
  2. Если вы определяете свой класс так, как вы это делаете, компилятор также будет ждать определения, которое находится в DLL (и эта DLL не предоставляет .lib с таблицей определений). Это означает, что код не будет компилироваться.
  3. Чтобы исправить это, вы можете:
    • Вы также экспортируете класс, компилятор создает файл .lib (по крайней мере, в VS) и связывает с ним ваше приложение, а это означает, что все QLibrary код не нужен.
    • вы конвертируете свой класс в чистый виртуальный класс (здесь требуются только открытые члены), выводите его во внутренний класс DLL ( класс реализации) и использовать 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,

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]