从DLL访问类成员(NOT LIB !!!)

时间:2014-02-07 21:14:56

标签: c++ qt dll

我有一个DLL,我甚至有dll的头文件,但我没有实现dll的lib文件。我尝试使用QLibrary类加载dll并从中获取类实例。我在2小时后成功检索了类,但是当我尝试在对象上调用函数时,我得到了未解析的外部符号,告诉我dll没有正确导出。为简单起见,我使用以下来源重新创建了该问题: DLL-Project(testlibrary_global.hpp):

#ifndef TESTLIBRARY_GLOBAL_HPP
#define TESTLIBRARY_GLOBAL_HPP

#include <QtCore/qglobal.h>

#if defined(TESTLIBRARY_LIBRARY)
#  define TESTLIBRARYSHARED_EXPORT Q_DECL_EXPORT
#else
#  define TESTLIBRARYSHARED_EXPORT Q_DECL_IMPORT
#endif

#endif // TESTLIBRARY_GLOBAL_HPP

DLL-Project(testlibrary.hpp):

#ifndef TESTLIBRARY_HPP
#define TESTLIBRARY_HPP

#include "testlibrary_global.hpp"

#include <QDebug>

class TESTLIBRARYSHARED_EXPORT TestLibrary {
public:
    TestLibrary();
    ~TestLibrary();
    void Test();
};

extern "C" TESTLIBRARYSHARED_EXPORT TestLibrary* getInstance();

#endif // TESTLIBRARY_HPP

DLL-Project(testlibrary.cpp):

#include "testlibrary.hpp"


TestLibrary::TestLibrary() {
    qDebug() << "Constructor called!";
}

TestLibrary::~TestLibrary() {
    qDebug() << "Destructor called!";
}

void Test() {
    qDebug() << "Hello from library!";
}


TestLibrary *getInstance() {
    return new TestLibrary();
}

这是非常直接的,不包含任何真正的花哨。正如你所看到的那样,我保持了类的默认值,因为QtCreator确实没有改变任何东西,除了添加了另一个带有extern“C”的函数和导出在global中定义的函数。这样做的目的是从dll本身获取一个对象,(因为我有.h和.dll没有别的)。现在对于加载器应用程序来说,再次是简单而简单的基本内容:

#include <QCoreApplication>
#include <QLibrary>
#include <QDebug>

#include "testlibrary.hpp"

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    QString libPath = QString("C:/Users/johorvat/Documents/QTProjects/build-TestLibrary-Desktop_Qt_5_2_0_MSVC2010_32bit_OpenGL-Debug/debug/TestLibrary.dll");
    QLibrary lib(libPath);
    bool loaded = lib.load();
    QString error = lib.errorString();
    qDebug() << "Loaded: " << loaded;

    typedef TestLibrary* (*Prototype)();
    Prototype Func = (Prototype) lib.resolve("getInstance");
    if (Func) {
        TestLibrary* tl = Func();
        if (tl) {
            qDebug() << "Yey, I gotta clazz!";
        }
    }

    return a.exec();
}

我将头文件添加到项目中,因为无论如何我都拥有它。我使用QLibrary来加载dll并从中检索getInstance方法,我可以使用它获取TestLibrary类的实例。但是,如果我尝试在if(tl){...}中调用TestLibrary的Test()方法,我会得到一个未解析的外部符号错误消息,告诉我它无法找到Test方法的定义。 我在这里缺少什么?

P.S。:我不会得到lib文件,所以让我们关注dll加载的问题:)。

此致  乔伊

1 个答案:

答案 0 :(得分:2)

好了,因为您已在void Test() {文件中写了.cpp而不是void TestLibrary::Test {,因此您的功能未被定义,因此根本不会导出。

编辑: 在这样的代码工作正常并在qDebug中打印“Hello”(dll应该在调试中编译,我第一次失败了)

QFunctionPointer raw = lib.resolve("?Test@TestLibrary@@QEAAXXZ");
TestPrototype testFunc;
*(QFunctionPointer*) &testFunc = raw;
(tl->*testFunc) ();

装饰函数名称不是很好但我不知道究竟可以做些什么:)而且你会得到不同编译器的不同名称,所以在这种情况下使用Qt不会是跨平台的