QtCreator Dll einbinden



  • moin zusammen

    nachdem ich nun schon etliche stunden damit verbraten habe, zu versuchen, eine dll in mein projekt einzubinden, hoffe ich, dass mir jemand den richtigen tipp geben kann 🙂

    folgende situation:
    im SDK von einem USB interface (ein SOUNDLIGHT DMX interface, falls es was zur sache tut) liegen eine dll und eine header datei bei, in der aber nur konstanten definiert sind.

    das meiner meinung nach beste ergebnis meiner suche wäre das hier:
    http://www.emmestech.com/moron_guides/moron1.html

    ich habe mich auch an das tut gehalten (soweit es geht, habe nicht alle tools gekriegt)

    aber ich kriege folgenden fehler:
    C:\Users\Jeremin\Documents\QT\DMXTest-build-desktop\..\DMXTest\dmxtest.cpp:16: Fehler:undefined reference to `DasUsbCommand(int, int, unsigned char*)'

    im moment schwimme ich im dll dschungel und habe keinen plan mehr, wo ich überhaupt ansetzen muss.
    daher bin ich für jeden tipp dankbar^^

    danke
    jeremin



  • gibt es neben dem header und der dll auch eine .lib datei (mit dem sleben namen wie die dll)?

    Und wie sieht die .pro datei deines qt-creator projektes aus?



  • nein, .lib datei gibt es eben leider keine und an deren erzeugung bin ich gescheitert.

    das .pro file sieht folgendermassen aus:

    #-------------------------------------------------
    #
    # Project created by QtCreator 2011-07-21T00:09:53
    #
    #-------------------------------------------------
    
    QT       += core gui
    
    TARGET = DMXTest
    TEMPLATE = app
    
    LIBS += -ldashard2006
    
    SOURCES += main.cpp\
            dmxtest.cpp
    
    HEADERS  += dmxtest.h \
        _DasHard2006.h
    
    FORMS    += dmxtest.ui
    

    mit LIBS += -lwinmm konnte ich in einem anderen projekt die winmm erfolgreich einbinden, nur ist dafür irgendwo im mingw verzeichnis auch die entsprechende .lib zu finden.

    im dem SDK beiliegenden pdf steht noch folgendes:
    The DasHard2006.dll contains only one function :
    int DasUsbCommand( int command, int param, unsigned char *bloc );
    ...
    [liste der zur verfügung stehenden befehle]
    ...
    Remarks:
    - All the constants DHC_OPEN, DHC_CLOSE, DHE_OK .... are defined in the "_DasHard.h"
    include file.

    soweit ich das begriffen habe geht es darum, eine .lib datei zu erzeugen, damit ich auf die dll zugreifen kann, oder?

    danke euch
    jeremin



  • jap entweder du erstellst dir eine lib für die dll oder verwendets loadlibrary zum laden der dll.

    Zum erstellen einer lib für eine dll siehe hier: http://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/



  • fein, das erstellen des .lib files scheint jetzt geklappt zu haben, danke 🙂

    ich bekomme aber immer noch fehler:

    4x (2x für jeden aufruf im code)
    C:\Users\Jeremin\Documents\QT\DMXTest-build-desktop\..\DMXTest\dmxtest.cpp:15: Fehler:'DasUsbCommand' was not declared in this scope

    1x
    👎 Fehler:collect2: ld returned 1 exit status

    gemäss google heisse das, dass er die library nicht findet (Quelle). leider kann ich aus dem kontext nicht erkennen, ob es um die .lib oder die dll geht, auch die fehlermeldung liefert nicht mehr informationen (oder kann ich irgendwo ein detailierteres log finden?)

    was ich getan habe:
    die erstellte .lib datei heisst DasHard2006.lib, also genau so wie die dll.
    ich habe in der .pro datei den pfad angepasst:

    LIBS += -L"C:\siudi\siudiUsb_developerkit\srcKopie\" -lDasHard2006

    ausserdem hab ich die dll in den debug unterordner im buildordner meines projektes kopiert.
    und in der headerdatei noch die funktion gemäss pdf definiert:
    int DasUsbCommand(int command, int param, unsigned char *bloc);
    (wenn ich das sein lasse, krieg ich nur einmal diesen fehler:

    C:\Users\Jeremin\Documents\QT\DMXTest-build-desktop\..\DMXTest\dmxtest.cpp:15: Fehler:'DasUsbCommand' was not declared in this scope

    und den finde ich unglaub nichtssagend :S)

    irgendwo muss die ja auch defiert werden, oder hab ich was elementares falsch verstanden?

    thx 🙂
    jeremin



  • doch die Fehlermeldung ist schon aussage kräftig und hat nichts mit der lib zu tun.

    C:\Users\Jeremin\Documents\QT\DMXTest-build-desktop\..\DMXTest\dmxtest.cpp:15: Fehler:'DasUsbCommand' was not declared in this scope

    der compiler kann keine Variable oder funktion finden, welche den namen DasUsbCommand heißt.

    Hast du überhaupt den header _DasHard2006.h in dmxtest.cpp eingebunden?



  • ja, die header-datei ist eingebunden, die konstanten werden auch erkannt.
    ich habe aber grad gemerkt, dass ich gestern was falsches geschrieben habe:

    wenn ich im headerfile die funktion definiere, bekomme ich 4 mal folgenden fehler:

    C:\Users\Jeremin\Documents\QT\DMXTest-build-desktop\..\DMXTest\dmxtest.cpp:16: Fehler:undefined reference to `DasUsbCommand(int, int, unsigned char*)'

    und nicht 4 mal:

    C:\Users\Jeremin\Documents\QT\DMXTest-build-desktop\..\DMXTest\dmxtest.cpp:15: Fehler:'DasUsbCommand' was not declared in this scope

    dieser fehler tritt nur auf, wenn ich die funktion nicht definiere (was ja irgendwie logisch ist, ich weiss nicht, warum ich gestern nicht selbst drauf gekommen bin :S)

    sorry dafür 😞
    das heisst wohl, dass er immernoch nicht weiss, wo er die funktion der dll finden kann, oder?



  • ?? wiso definierst du selbst die funktion?
    Die definition der funktion sollte im header stehen.

    Und der fehler hat nichts mit der DLL zu tun, es ist ein compiler fehler und kein fehler des linkers.
    Wie ich schon sagte kann der Compile keine definition einer Funktion mit dem Namen DasUsbCommand finden.

    Zeig mal den inhalt des headers (falls es dir gestattet ist).



  • steht sie aber nicht 😞

    #ifndef DASHARD_H
    #define DASHARD_H
    
    #define DHC_SIUDI0				0		// COMMAND
    #define DHC_SIUDI1				100		// COMMAND
    #define DHC_SIUDI2				200		// COMMAND
    #define DHC_SIUDI3				300		// COMMAND
    #define DHC_SIUDI4				400		// COMMAND
    #define DHC_SIUDI5				500		// COMMAND
    #define DHC_SIUDI6				600		// COMMAND
    #define DHC_SIUDI7				700		// COMMAND
    #define DHC_SIUDI8				800		// COMMAND
    #define DHC_SIUDI9				900		// COMMAND
    
    #define DHC_OPEN				1		// COMMAND
    #define DHC_CLOSE				2		// COMMAND
    #define DHC_DMXOUTOFF			3		// COMMAND
    #define DHC_DMXOUT				4		// COMMAND
    #define DHC_PORTREAD			5		// COMMAND
    #define DHC_PORTCONFIG			6		// COMMAND
    #define DHC_VERSION				7		// COMMAND
    #define DHC_DMXIN				8		// COMMAND
    #define DHC_INIT				9		// COMMAND
    #define DHC_EXIT				10		// COMMAND
    #define DHC_DMXSCODE			11		// COMMAND
    #define DHC_DMX2ENABLE			12		// COMMAND
    #define DHC_DMX2OUT				13		// COMMAND
    #define DHC_SERIAL				14		// COMMAND
    #define DHC_TRANSPORT			15		// COMMAND
    #define DHC_DMXENABLE			16		// COMMAND
    #define DHC_DMX3ENABLE			17		// COMMAND
    #define DHC_DMX3OUT				18		// COMMAND
    #define DHC_DMX2IN				19		// COMMAND
    #define DHC_DMX3IN				20		// COMMAND
    
    #define DHC_WRITEMEMORY			21		// COMMAND
    #define DHC_READMEMORY			22		// COMMAND
    #define DHC_SIZEMEMORY			23		// COMMAND
    
    #define DHE_OK					1		// RETURN NO ERROR
    #define DHE_NOTHINGTODO			2		// RETURN NO ERROR
    
    #define DHE_ERROR_COMMAND		-1		// RETURN ERROR
    #define DHE_ERROR_NOTOPEN		-2		// RETURN ERROR
    #define DHE_ERROR_ALREADYOPEN	-12		// RETURN ERROR
    
    typedef struct{
    	WORD year;  
    	WORD month;  
    	WORD dayOfWeek;  
    	WORD date;  
    	WORD hour;  
    	WORD min;  
    	WORD sec;  
    	WORD milliseconds;
    }STIME;
    
    #endif
    

    das ist der unabgeänderte header.
    ich habe das struct am ende auskommentiert, da Qt WORD so direkt nicht zu kennen scheint, aber ich habe das struct auch noch nie gebraucht. (ich habe früher mal etwas mit dem gleichen SDK in VB geschrieben, nur konnte ich dort ein vorhandenes projekt ändern)
    ausserdem wie schon erwähnt die definition der funktion, denn die muss ja irgendwo definiert werden.

    hier ist noch der link zum SDK, wenn es weiter helfen sollte:
    http://www.dmxsoft.com/global/ftp/siudi_usb_developerkit.exe

    undefined reference heisst doch, dass der funktion body nirgends gefunden worde, oder?

    gruss
    jeremin



  • [gg]Nein heißt es nicht. Es heißt, dass der Compiler keine definition einer Funkion mit dem namen finden kann.

    Das SDK an sich ist echt schei**e. Da liefern die ne DLL und nen Header aber im Header ist die Methode nicht definiert. Und es gibt auch keine *.lib Datei zum linken. Die kommen echt aus der Delphi/VB ecke wo sowas scheinbar nicht notwendig ist

    In dem SDK gibt es auch ein c++ Beispiel (slmini2006). Dort verwenden die LoadLibrary um die DLL zur laufzeit zu laden.

    Da du ja schon die *.lib hast sollte folgende helfen, das zumindestens der Compiler zufrieden ist:

    Füge folgende Zeile dem Header der DLL hinzu:

    int DasUsbCommand(int, int, unsigned char*);
    

    Dann sollte der compiler die funktion kennen.



  • ok 🙂

    ich habs vor ein paar jahren mal geschafft, die dll in den borland c++ builder einzubinden, aber der steht mir jetzt nicht mehr zur verfügung (damals konnte ich ihn von der schule her nutzen), und es war schon damals ein drama 😞

    firefly schrieb:

    Da du ja schon die *.lib hast sollte folgende helfen, das zumindestens der Compiler zufrieden ist:

    Füge folgende Zeile dem Header der DLL hinzu:

    int DasUsbCommand(int, int, unsigned char*);
    

    Dann sollte der compiler die funktion kennen.

    tut er leider nicht, immer noch 4x

    C:\Users\Jeremin\Documents\QT\DMXTest-build-desktop\..\DMXTest\dmxtest.cpp:15: Fehler:undefined reference to `DasUsbCommand(int, int, unsigned char*)'

    und einmal:
    👎 Fehler:collect2: ld returned 1 exit status

    zur sicherheit mal noch den code aus der dmxtest.cpp, vielleicht hat sich dort noch nen fehler eingeschlichen:

    #include "dmxtest.h"
    #include "ui_dmxtest.h"
    
    #include "_DasHard2006.h"
    
    DMXTest::DMXTest(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::DMXTest)
    {
        ui->setupUi(this);
    
        int interfaceOpen;
        unsigned char dmxBlock[512];
    
        DasUsbCommand(DHC_INIT,0, NULL);
        interfaceOpen = DasUsbCommand(DHC_OPEN,0,0);
        ui->label->setText(QString(interfaceOpen));
    
        if (interfaceOpen>0){
            for(int i=0;i<512;i++)
                dmxBlock[i] = 0;
        }
    }
    
    DMXTest::~DMXTest()
    {
        delete ui;
    }
    

    ich habe gestern beim suchen noch entdeckt, dass Qt selber eine klasse QLibrary bereitstellt und die winAPI die im SDK verwende LoadLibrary funktion.
    der unterschied ist ja, dass bei diesen beiden lösungen die dll erst zur laufzeit geladen wird, im gegensatz zum bisher beschrittenen weg, aber hat das sonst noch auswirkungen?
    weil langsam überlege ich mir, dass anders zu lösen 😛
    oder hab ichs nur versaut, die .lib richtig zu erstellen, kann man die irgendwie überprüfen?

    danke für die mühe! 🙂



  • ups da lag ich wohl falsch. Wenn als letzte meldung

    ehler:collect2: ld returned 1 exit status

    kommt, dann ist es doch ein linker problem.

    hast du die erstellte lib ins C:\siudi\siudiUsb_developerkit\srcKopie\ verzeichnis kopiert?

    Ansonsten bleibt dir doch nichts anderes übrig als die DLL zur laufzeit "manuell" zu laden.

    Der Nachteil an der Methode ist, dass du dich selbst um das saubere entladen der DLL wieder kümmeern musst.



  • ja, die lib befindet sich dort.
    muss ich bei der namesvergabe irgendwas beachten?
    habe es bis jetzt mit DasHard2006.lib und libDasHard2006.lib versucht.

    sonst muss ich mir halt wirklich mal noch die syntax von QLibrary genauer ansehen.



  • die *.lib muss den gleichen namen haben wie die DLL.

    Kann es sein, dass du als qt-creator mit dem mingw compiler verwendest?

    eventuell hilft dir das hier eine passende import lib (*.lib) zu erstellen:
    http://www.mingw.org/wiki/CreateImportLibraries



  • ich benutze das standard qt IDE mit einem mingw verzeichnis, daher geh ich mal davon aus, dass ich mingw habe.

    gestern abend habe ich deinen link noch ausprobiert, hat leider nichts gebracht, obwohl es sehr vielverprechend aussah (es hat zb nen delphi dll beispiel)
    ausserdem habe ich noch folgenden weg versucht: klick mich
    das scheiterte aber schon daran, das reimp mir ein leeres .def file erstellte 😞

    heute morgen habe ich noch per google den beitrag gefunden:
    http://www.c-plusplus.net/forum/p719609#719609

    hab auch diese anleitung schritt für schritt befolgt, aber immernoch die gleichen fehler.

    zu guter letzt habe ich auch noch eine mail an die adresse im pdf des SDK's geschickt, mit der bitte um eine .lib oder eine .a, falls da nichts kommt, muss ich wohl oder übel den weg über Qlibrary wählen 😞

    nur noch eine frage:
    int DasUsbCommand(int command, int param, unsigned char *bloc);

    reicht das wirklich aus als definition?
    weil ich habe mein altes projekt mit dem c++ builder noch auf einem USB stick gefunden, da lautete die definition folgendermassen:

    extern "C" {
    	_declspec(dllimport) int DasUsbCommand(int command, int param, unsigned char *bloc);
    }
    

    im übrigen hatte ich im damaligen .def file noch ein @1 hinter dem funktions namen, was ich jetzt einfach nicht hinbekommen habe 🙂
    allerdings scheint es auch eine leicht andere dll zu sein, die jetztige ist ca 5x grösser 😮
    ich schau mal, ob ich die alte zum laufen kriege.



  • Das

    extern "C" {
        int DasUsbCommand(int command, int param, unsigned char *bloc);
    }
    

    ist elementar wichtig, da in C function-Symbole anders sind als in C++. Das _declspec(dllimport) kannst du auch weglassen.

    Kleiner Tipp noch. Vermeide Backslash. D.h.
    `

    LIBS += -L"C:/siudi/siudiUsb_developerkit/srcKopie" -lDasHard2006

    `



  • holzeimer schrieb:

    Das

    extern "C" {
        int DasUsbCommand(int command, int param, unsigned char *bloc);
    }
    

    ist elementar wichtig, da in C function-Symbole anders sind als in C++. Das _declspec(dllimport) kannst du auch weglassen.

    Kleiner Tipp noch. Vermeide Backslash. D.h.
    `

    LIBS += -L"C:/siudi/siudiUsb_developerkit/srcKopie" -lDasHard2006

    `

    oder mit $$quote(<text>) arbeiten, dann klappt es auch mit dem backslash



  • holzeimer schrieb:

    Das

    extern "C" {
        int DasUsbCommand(int command, int param, unsigned char *bloc);
    }
    

    ist elementar wichtig, da in C function-Symbole anders sind als in C++. Das _declspec(dllimport) kannst du auch weglassen.

    Kleiner Tipp noch. Vermeide Backslash. D.h.
    `

    LIBS += -L"C:/siudi/siudiUsb_developerkit/srcKopie" -lDasHard2006

    `

    habe ich beides ausprobiert, leider nix geholfen.

    dafür habe ich heute morgen eine antwort auf das mail erhalten:

    You don't need an lib file to use our dll with the Qt IDE.
    You can use it like in our Vc++ sample.

    tja, dann mach ichs halt mittels LoadLibrary, bzw. eher mittels QLibrary, ist mir sympathischer 🙂
    aber jetzt muss erst mal 2-3 wochen mit prüfungen verbringen, dann mache ich einen neuen versuch, diese dll einzubinden.

    auf jedenfall danke auch (vorallem firefly) für die hilfe 😃

    schönen abend
    jeremin



  • In dem Beispiel slmini.cpp ist doch alles drin was man braucht ?

    #include "_DasHard.h"
    
    HINSTANCE g_dasusbdll = NULL;
    typedef int (*DASHARDCOMMAND)(int, int, unsigned char*);
    DASHARDCOMMAND  DasUsbCommand = NULL;
    
    int HardDllOpen()
    {
    	g_dasusbdll = LoadLibrary("DasHard2006.dll");
    
    	if (g_dasusbdll)
    		DasUsbCommand  = (DASHARDCOMMAND)::GetProcAddress((HMODULE)g_dasusbdll, "DasUsbCommand");
    	if (DasUsbCommand)
    		return 1;
    	return 0;
    }
    
    int HardDllClose()
    {
    	if (g_dasusbdll!=NULL)
    		return	FreeLibrary(g_dasusbdll);
    	return 0;
    }
    
    int HardDllCommand(int command, int param, unsigned char *bloc)
    {
    	if (DasUsbCommand)
    		return (*DasUsbCommand)(command, param, bloc);
    	return 0;
    }
    

    Der Code sieht doch recht plausibel aus ...



  • also wenn ich das 1 zu 1 in Qt übernehmen kann, sag ich natürlich nicht nein 🙂
    aber ich werde mich erst in 2-3 wochen wieder dahinter setzen.

    gruss
    jeremin


Log in to reply