Hallo, ich habe dasselbe Problem wie ein Nutzer in einem älteren Beitrag: Beitrag ""nackte" DLL einbinden (Qt)" Zitat: "Ich versuche eine .dll (von dem PC-Oszilloskope PCSGU250) in ein Qt-Projekt einzubinden. In der Zip vom Hersteller befindet sich keine .a .lib .def oder .h sondern nur die .dll, eine .bit und ein paar Beispiele für delphi und VS." Anstatt Header, .lib, .def, etc zu erstellen, möchte ich die .dll gerne dynamisch mit QLibrary laden. Hierfür, schätze ich, brauche ich ebenfalls den "extern-"C"-Befehl", weiß jedoch nicht, wo und wie ich diesen einsetzen soll. Beispielsweise habe ich als ersten Test Folgendes versucht, um die dll einzubinden: QLibrary library("PCSGU250.dll"); if(library.load()) cout <<"Library loaded"; Hierbei kann QT die dll jedoch nicht finden. Da ich mit dem dynamischen Laden einer dll über die QLibrary völlig unerfahren bin, freue ich mich über jegliche Hilfe und Hinweise! Beste Grüße und vielen Dank, Magdalena
Ich hab das auch schon versucht. Das blöde ist nur, dass man genau wissen muss, wie die Funktionen heißen und welche Parameter übergeben werden müssen.
Mathias O. schrieb: > Ich hab das auch schon versucht. Das blöde ist nur, dass man genau > wissen muss, wie die Funktionen heißen und welche Parameter übergeben > werden müssen. Genau, das ist ein allgemeines Problem, das lässt sich aber z.B. Problemlos mit dem Dependency Walker anschauen: http://www.dependencywalker.com/ z.B. hier findet man den Passenden Screenshot: http://1.f.ix.de/imagine/swvz-programme/F5a7iHuJWliMfQ074CMcBCx9lsw/content/Dependency-Walker.jpg Der Rest ist etwas Fleissarbeit... Edit: Hier noch das Beispiel, die daten siehst du beim Dependency Walker, so musst du das dann im Code erfassen: http://doc.qt.io/qt-4.8/qlibrary.html#resolve mfg Andreas
:
Bearbeitet durch User
Mathias O. schrieb: > Ist nur blöd, wenn die Dll in .Net geschrieben ist ;). Ist sie aber nicht, es handelt sich um eine einfache Win32-DLL mit ca. 20 Funktionen. Mathias O. schrieb: > Das blöde ist nur, dass man genau wissen muss, wie die Funktionen heißen > und welche Parameter übergeben werden müssen. Das steht doch alles in der Datei "Make your own software for the PCSGU250.pdf".
Abgesehen davon wäre es bei einer .NET-DLL ja noch einfacher, exportierte Funktionen zu verwenden (einfach die DLL als Referenz einbinden).
Ok, in C++ (nicht C++/CLI) natürlich nicht ... (verflixt, ich sollte mich einloggen).
Wurfwanze schrieb: > Ist sie aber nicht, es handelt sich um eine einfache Win32-DLL mit ca. > 20 Funktionen. Meine nicht. Meine ist von Epson um einen Epson Roboter anzusprechen. Hab ja nicht gesagt, dass ich es mit der selben Dll versucht habe. Wurfwanze schrieb: > Abgesehen davon wäre es bei einer .NET-DLL ja noch einfacher, > exportierte Funktionen zu verwenden (einfach die DLL als Referenz > einbinden). Und das geht genau wie im Qt Creator?
Hallo, vielen Dank zunächst für die vielen Antworten! Für die Funktionen habe ich eine Liste, weiß also, welche Funktionen enthalten sind. Muss ich diese Funktionen einzeln mit extern c oder so ähnlich einbinden oder geht das für mehrere Funktionen zugleich? Wie funktioniert in diesem Fall der extern C Befehl? Die Antworten sind jedenfalls schon sehr hilfreich!! :)
Magdalena M. schrieb: > Muss ich diese Funktionen einzeln mit extern c oder so ähnlich > einbinden oder geht das für mehrere Funktionen zugleich? Wie > funktioniert in diesem Fall der extern C Befehl? Du brauchst Funktionspointer, für jede Funktion, die Du aufrufen möchtest, einen einzelnen. Da die Aufrufe C-Code (und kein C++-Code) sind, also ohne "name mangling" arbeiten, musst Du Definition und gegebenenfalls Deklaration dieser Funktionspointer in "extern C"-Abschnitten durchführen.
Hallo nochmal, wenn ich eine Header-Datei erstellen möchte mit den Informationen aus der Datei "Make your own software...", in der die Funktionen aufgeführt sind, wie muss ich da vorgehen? Die Funktionen in der Datei sind nicht in C++ geschrieben, sondern für Delphi, gibt es dafür eine bestimmte Methode, sie umzuschreiben, sodass mit der .dll gearbeitet werden kann? Mit dem Dependency Walker bekomme ich folgendes Ergebnis(siehe Bild), es werden mir also die Namen der verschiedenen Funktionen angezeigt, jedoch keine Datentypen für Variablen. Ist da noch etwas einstellbar?
Magdalena M. schrieb: > jedoch keine Datentypen für Variablen. Ist da noch etwas einstellbar? Nein, diese Informationen stehen in der DLL nicht drin, die musst Du der Dokumentation der DLL entnehmen.
Ok, die .dll wird jetzt von Qt gefunden, jedoch erscheinen (logischerweise) zahlreiche Fehler, die folgendermaßen aussehen: stray"\"Zahl"" in program (mit einer beliebigen Zahl) Was genau bedeutet dieser Fehler? Habe jetzt noch keine Header und keine .lib eingebunden, da ich bei der Header nicht weiß, wie ich sie erstellen soll. In der Dokumentation steht beispielsweise für eine Funktion: PROCEDURE Start_PCSGU250: Boolean; Wie muss ich im Header etwas zu dieser Funktion angeben? Ist hier void Start_PCSGU250(void); korrekt? Gibt es einen Weg, sich eine Header Datei erstellen zu lassen durch eine Software? Ist es weiterhin norwendig, auch die lib einzubinden? Vielen Dank schonmal :)
Schau doch z.B. hier: http://forum.velleman.eu/viewtopic.php?f=10&t=8900 Andere Leute haben dieses Gerät auch...
Magdalena M. schrieb: > PROCEDURE Start_PCSGU250: Boolean; > > Wie muss ich im Header etwas zu dieser Funktion angeben? > Ist hier > void Start_PCSGU250(void); > korrekt? Und da steht z.B. doch was von bool, warum also void?
Magdalena M. schrieb: > In der Dokumentation steht beispielsweise für eine Funktion: > > PROCEDURE Start_PCSGU250: Boolean; > > Wie muss ich im Header etwas zu dieser Funktion angeben? > Ist hier > void Start_PCSGU250(void); > korrekt? Hmm ... Ich kenne Delphi nicht, aber ich würde mich fragen, warum dort Boolean steht und davon ausgehen, dass void/void nicht richtig sein kann ;). Und dann würde ich nachsehen, was PROCEDURE und FUNCTION bedeutet und mir eine Liste mit den Delphi-Datentypen und deren Eigenschaften suchen. Man könnte dann nachsehen und/oder sich überlegen, wie man die Datentypen in C übersetzt. Magdalena M. schrieb: > Gibt es einen Weg, sich eine Header Datei erstellen zu lassen durch eine > Software? Die Signaturen der Funktionen sind so simpel, dass das Schreiben der C-Funktionsprototypen nicht sooo schwierig sein dürfte. Aber physiker hat ja dir ja schon einen Link gegeben. > Ist es weiterhin norwendig, auch die lib einzubinden? Welche lib?
Weil du doch die .h oder .lib nicht hast, musst du doch QLibrary nehmen. Sonst könntest du ja auch den normalen Weg nehmen und das ganze über das pro-File einbinden. Nun sollte es doch so einfach funktionieren:
1 | QLibrary lib("PCSGU250.dll"); |
2 | typedef bool (*protoBool)(); |
3 | protoBool funcStart = (protoBool) lib.resolve("Start_PCSGU250"); |
4 | if (funcStart) |
5 | qDebug() << funcStart(); |
Mathias O. schrieb: > Weil du doch die .h oder .lib nicht hast, musst du doch QLibrary nehmen. > Sonst könntest du ja auch den normalen Weg nehmen und das ganze über das > pro-File einbinden. In der Zwischenzeit konnte ich mir die .lib erstellen und versuche jetzt, die Header zu erstellen. > Nun sollte es doch so einfach funktionieren: >
1 | QLibrary lib("PCSGU250.dll"); |
2 | > typedef bool (*protoBool)(); |
3 | > protoBool funcStart = (protoBool) lib.resolve("Start_PCSGU250"); |
4 | > if (funcStart) |
5 | > qDebug() << funcStart(); |
Mit diesem Code bekomme ich ebenfalls die Fehlermeldungen mit stray '\2' in program (mit verschiedenen Zahl hinter \) Woher dieser Fehler kommt, konnte ich mir noch nicht erklären...
Dann brauchst du ja QLibrary nicht mehr und kannst den üblichen Weg gehen. Hilft Google bei den Fehler nicht weiter? https://www.google.de/#q=stray+%27\2%27+in+program
Ja, ich versuche zumindest gerade, den normalen Weg zu gehen, scheitere aber wie gesagt an der Erstellung der Header, bzw. bin mir, was meine Header angeht nicht sicher. Das Problem ist eben dieser Fehler. Hatte ihn, als ihn zum ersten Mal hatte, bereits gegooglet und nach einem ähnlichen Fall gesucht. Zumeist tritt dieser Fehler wohl auf, wenn Code per Copy&Paste übernommen wird, was bei mir nicht der Fall ist. Zudem sagt die Fehlermeldung, die Fehler seien in der .dll aufgetreten, daher weiß ich nicht, wie ich dort etwas verändern soll...
Magdalena M. schrieb: > Zudem sagt die Fehlermeldung, die Fehler seien in der .dll aufgetreten Das glaube ich jetzt eher weniger. Die "stray irgendwas in program" Fehlermeldung kommt vom Compiler. Eine DLL ist bereits kompiliert, die wird dazugelinkt.
Mark B. schrieb: > Magdalena M. schrieb: >> Zudem sagt die Fehlermeldung, die Fehler seien in der .dll aufgetreten > > Das glaube ich jetzt eher weniger. Die "stray irgendwas in program" > Fehlermeldung kommt vom Compiler. Eine DLL ist bereits kompiliert, die > wird dazugelinkt. Vermutlich irgendwo im Source code versehentlich ein unsichtbares Sonderzeichen untergebracht. Sowas kann man in einem Hex-Editor finden und eliminieren.
Vielleicht wird ja die DLL dem Compiler als Quellcodedatei verkauft. Dann könnte auch so eine Fehlermeldung kommen. Wie sieht denn die komplette Meldung aus?
Die dll habe ich eingebunden, indem ich im .pro file den Pfad angegeben habe und in der main datei include "PCSGU250.dll" verwendet habe. Ich weiß nicht, ob dies der korrekte Weg ist oder die Datei so als Quellcode erkannt wird... Die Fehlermeldung (also ein Beispiel) habe ich angefügt. Wenn ein Sonderzeichen der Grund ist, wie finde ich es dann it einem Hex Editor? Bei 28000 dieser Fehler, sind es dann nicht viel zu viele Sonderzeichen?
Magdalena M. schrieb: > include "PCSGU250.dll" Das geht nicht. Das ist grundlegend und vollkommen falsch. Lies ein C-Buch. Sieh Dir an, was man mit #include einbinden kann.
Magdalena M. schrieb: > include "PCSGU250.dll" Aua :-) Eine DLL kann man nicht inkludieren. Die wird vom Linker (das ist der, der nach dem Compiler drankommt) hinzugelinkt. Ich kenne jetzt Deine Entwicklungsumgebung nicht. Aber irgendwo in den Projekteinstellungen gibt es sicher die Möglichkeit, dem Linker mitzuteilen dass er diese oder jene Datei hinzu linken soll. Das ist der Weg den Du wahrscheinlich gehen willst. Bzw. wenn ich das hier lese: Magdalena M. schrieb: > In der Zip vom Hersteller befindet sich keine .a .lib .def oder .h > sondern nur die .dll, eine .bit und ein paar Beispiele für delphi und > VS. dann fehlt ja gerade die .lib Datei zum Linken. Also muss man die DLL wohl dynamisch zur Laufzeit laden. Nichtsdestotrotz sollte es in der Entwicklungsumgebung die Möglichkeit geben, den Pfad zu solchen Dateien anzugeben bzw. die Linker-Einstellungen mit entsprechenden Parametern zu ergänzen.
:
Bearbeitet durch User
Mark B. schrieb: > Also muss man die DLL wohl dynamisch zur Laufzeit laden. > Nichtsdestotrotz sollte es in der Entwicklungsumgebung die Möglichkeit > geben, den Pfad zu solchen Dateien anzugeben Wozu? Wenn man sie dynamisch zur Laufzeit lädt, hat das mit der Entwicklungsumgebung nichts zu tun. Aber um sie dynamisch zur Laufzeit zu laden, bedarf es Informationen über die in der DLL enthaltenen Funktionen, d.h. die Funktionsprototypen. Es sei denn, diese DLL verwendet (D)COM-Automation und will "installiert", d.h. dem (D)COM-Gekröse von Windows bekanntgemacht werden. Dann kann man die DLL mit jeder Sprache ansprechen, die Automationsobjekte anfordern und bedienen kann, also z.B. auch VBScript. --- Nein, das ist nicht der Fall, das Ding verwendet keine Automation. Bei der DLL handelt es sich um diese hier: https://www.velleman.eu/downloads/files/downloads/pcsgu250_dll_rev1.zip Das Ding ist in erster Linie für Delphi-Anwender beschrieben. Codebeispiele sind für Delph und Visual Basic(.net) vorhanden. Die verwendete VB.net-Version ist VB.net express 2008.
:
Bearbeitet durch User
Magdalena M. schrieb: > Die dll habe ich eingebunden, indem ich im .pro file den Pfad angegeben > habe und in der main datei > > include "PCSGU250.dll" > > verwendet habe. Damit wird klar, woher die Fehlermeldung kommt. > Ich weiß nicht, ob dies der korrekte Weg ist oder die Datei so als > Quellcode erkannt wird... Wird sie. Der Präprozessor nimmt ihren kompletten Inhalt und fügt den so wie er ist an der Stelle, wo das #include steht, im Quellcode ein. Dann läuft der Compiler drüber, der damit natürlich nichts anfangen kann, weil es Binärdaten sind und kein C++-Code.
Ok, ich habe meinen Fehler eingesehen. Das mit dem "include" war nur so eine spontane Idee von mir, da ich mir nicht bewusst war, dass er die Binärdaten dann als Quellcode einliest. Habe es nun aber verstanden. Meine Hoffnung war, dass dieser Weg irgendwie zielführend sei, da die .dll zumindest erkannt wurde, aber so ist ja jetzt klar, was passiert ist. Zurzeit versuche ich weiterhin, die dll einzubinden mithilfe der aus der dll erstellten .lib und einer selbst erstellten Header-Datei. Die .lib binde ich folgenderweise im .pro file ein: win32:CONFIG(release, debug|release): LIBS += -L$$PWD/./ -lPCSGU250 else:unix: LIBS += -L$$PWD/./ -lPCSGU250 INCLUDEPATH += $$PWD/. DEPENDPATH += $$PWD/. Die Header-Datei binde ich in die .cpp mit include ein. Die .dll habe ich jetzt unter DistFiles im .pro file eingebunden, bin mir da aber nicht sicher, ob das richtig ist, bzw. wie die .dll direkt eingebunden werden soll. Ist dieser Weg soweit korrekt, bzw. was muss geändert werden?
Ich habe keine Ahnung von Qt, aber in VS wäre der einfachste Weg, sich per "dumpbin" und "lib" eine Library zu erstellen und diese sowie die (selbst geschriebene bzw. vom obigen Link abgewandelte) Header-Datei einzubinden. Die PCSGU250.dll muss natürlich im Ausgabeverzeichnis liegen, wenn das entsprechende Programm gestartet wird. Das folgendes Programm stürzt zumindest nicht ab und gibt true und false aus. Das ist natürlich kein "Beweis" der Funktionsfähigkeit, aber mehr kann ich ohne die Hardware nicht testen.
1 | #include <iostream> |
2 | #include "pcsgu250.h" |
3 | |
4 | int main() |
5 | { |
6 | std::cout << std::boolalpha << Start_PCSGU250() << std::endl; |
7 | |
8 | std::cout << DataReady() << std::endl;; |
9 | |
10 | return 0; |
11 | } |
Vielen Dank für die ausführliche und hilfreiche Antwort. Passenderweise war gerade an genau dem Punkt angelangt, dass ich mir true und false Werte anzeigen ließ für die Start_PCSGU250() Funktion. :) Die Antwort war aber trotzdem gut, damit ich weiß, dass mein Vorgehen soweit stimmt. Hattest du die Header-Datei geschrieben oder wo kam sie her? Sie deckt sich jedenfalls fast vollständig mit meiner erstellten Header-Datei, was mich schonmal beruhigt und das Anzeigen mit den true und false Werten funktioniert. Das Einbinden von .h und .lib scheint auf jeden Fall zu klappen, mal schauen, wie es jetzt weitergeht :)
Magdalena M. schrieb: > Hattest du die Header-Datei geschrieben oder wo kam sie her? Ich habe bloß von hier http://forum.velleman.eu/viewtopic.php?f=10&t=8900 kopiert (siehe Beitrag oben von 'physiker'), das .NET-Zeug gelöscht und extern "C" hinzugefügt. Ob alle Prototypen im Detail korrekt sind, habe ich aber nicht nachgeprüft.
Achso, ja klar. Hatte mir diese Header-Datei angeschaut, aber war verwirrt durch die Zusätze mit "extern" in jeder Zeile und das Ganze mit DLL-Import. :)
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.