2014-02-07 2 views
2

나는 DLL이 있고 심지어 DLL에 대한 헤더 파일도 있지만 구현 DLL 파일이 없습니다. 나는 QLibrary 클래스와 DLL을로드하고 그것으로부터 클래스 인스턴스를 얻으려고합니다. 2 시간 후에 클래스를 성공적으로 가져 왔지만 객체에 함수를 호출하려고하면 dll이 제대로 내보내지지 않았다는 것을 알 수있는 해결되지 않은 외부 심볼이 생깁니다. DLL-프로젝트 (testlibrary_global.hpp) :DLL에서 액세스하는 클래스 멤버 (NOT 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을로드하고 TestLibrary 클래스의 인스턴스를 얻을 수있는 getInstance 메소드를 검색했습니다. 그러나 if (tl) {...} 내에서 TestLibrary의 Test() 메서드를 호출하려고하면 Test 메서드의 정의를 찾을 수 없다는 해결되지 않은 외부 심볼 오류 메시지가 나타납니다. 여기에 무엇이 누락 되었습니까?

P.S. : 나는 lib 파일을 얻지 않을 것이므로 dll 로딩과 관련된 문제에 집중하겠습니다. :)

감사합니다, 당신이 당신의 .cpp 파일에 void Test() {을 작성했습니다하지 void TestLibrary::Test { 함수가 정의되지 않는 등이 전혀 수출되지 뭐 때문에 조이

+0

그래서 dll에 연결하는 방법에는 암시 적 연결과 명시 적 연결이 있습니다. 암시 적 링크를 사용하면 .lll 파일과 함께 .dll 파일을 제공하므로 링크하는 방법을 알려주는 .dll을 쉽게 찾을 수 있습니다. 이 기능이 없으면 명시 적 연결을 사용해야합니다 (http://stackoverflow.com/questions/20294545/how-to-use-ac-class-dll-loaded-explicitly-in-visual-studio 참조) – IdeaHat

+0

더 나은 링크 http://stackoverflow.com/questions/1027435/explicitly-linking-to-classes-in-dlls – IdeaHat

+1

DLL에서 C++ 클래스를 내보내는 것은 매우 나쁜 생각입니다. Windows에는 표준 바이너리 인터페이스가 없으며 모든 컴파일러 (동일한 컴파일러의 다른 버전과 같은 컴파일러의 동일한 버전에 전달 된 여러 컴파일러 옵션 포함)가 일치하지 않습니다. 일반 C 호환 시그니처를 사용하여 함수 내보내기를 사용하십시오. 오브젝트를 내보내려면 COM처럼 v 테이블을 사용하십시오. –

답변

2

.

편집 : 같은이 코드는 잘 작동하고 qDebug에서 인쇄 "안녕하세요"후 (DLL 디버그 컴파일해야한다, 내가 그 처음에 실패)

QFunctionPointer raw = lib.resolve("[email protected]@@QEAAXXZ"); 
TestPrototype testFunc; 
*(QFunctionPointer*) &testFunc = raw; 
(tl->*testFunc)(); 

장식 된 함수 이름은 매우 아니다 멋지지만 그것에 대해 정확히 할 수있는 일이 무엇인지 모르겠다. :) 그리고 다른 컴파일러를 사용하여 다른 이름으로 맹 글링 된 이름을 얻게 될 것이므로이 경우 Qt를 사용하면 어쨌든 크로스 플랫폼이되지 않을 것이다.

관련 문제