我有一個DLL,我甚至有DLL的頭文件,但我沒有執行DLL文件的lib文件。我嘗試使用QLibrary類加載dll並從中獲取類實例。我在2小時後成功地檢索了這個類,但是當我嘗試調用該對象的函數時,我得到了未解析的外部符號,它告訴我該dll沒有正確導出。爲了簡單起見,我重新創建具有下列來源問題: DLL項目(testlibrary_global.hpp):訪問類成員從DLL(不LIB !!!)
#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項目(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項目( 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」的函數和在全局中定義的導出。這樣做的目的是從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加載問題:)。
問候, 喬伊
所以有兩種方法可以鏈接到一個dll:隱式鏈接和顯式鏈接。通過隱式鏈接,它們會爲.dll文件提供一個.lib文件,告訴您如何鏈接,這讓我覺得更容易。如果你沒有這個,你必須使用顯式鏈接(請參閱http://stackoverflow.com/questions/20294545/how-to-use-ac-class-dll-loaded-explicitly-in-visual-studio) – IdeaHat
更好的鏈接http://stackoverflow.com/questions/1027435/explicitly-linking-to-classes-in-dlls – IdeaHat
試圖從DLL中導出C++類是一個非常糟糕的主意。 Windows沒有標準的二進制接口,並且每個C++編譯器(包括相同編譯器的不同版本,以及傳遞給相同編譯器的相同版本的不同編譯器選項)都不匹配。使用具有普通C兼容簽名的函數導出,並且如果要導出對象,請使用像COM一樣的V表。 –