Hallo zusammen,
ihr kennt doch bestimmt die Szene aus Malcom mittendrin, wo der Vater
die Glühbirne auswechseln soll und zum Schlus das Auto repariert...?
watch?v=epMzvVGI_s4
Eigentlich hänge ich ja gerade mit vier Füßen in der
FPGA-Programmierung, aber dabei brauche ich unter anderem einen
JTAG-Anschluss... also den FTDI-Chip benutzen, der eh daran hängt... und
dazu ein bisschen C# programmieren...
Tage später hänge ich nun an dieser Baustelle:
Das Code-Beispiel
http://www.ftdichip.com/Support/SoftwareExamples/MPSSE/FTCJTAG/CSharp/FT2232CJTAGCsharpTestApp_200.zip
definiert u.a.
Man beachte die Aufrufkonvention ".Cdecl" am Schluss der ersten Zeile
Ein Aufruf, kompiliert für DotNnet 3.5 funktioniert klaglos. Die Version
der DLL wird fehlerfrei mit 2.0 zurückgeliefert.
Das selbe Stück Code für DotNet 4.0 kompiliert schmeißt beim Debuggen
einen pinvokestackimbalance-error!
Tante Google meint dazu, dass
a) die Aufrufkonventionen meines Codes und die der DLL nicht
übereinstimmen
b) DotNet 3.5 die Fehler bisher defaultmäßig berücksichtigt hat
c) DotNet 4.0 das defaultmäßig nicht mehr tut, jedoch dazu überredet
werden kann
Nun möchte ich ja keinesfalls unsauber herumschlampen und habe deshalb
weiter nachgeforscht.
In den Header Dateien von FTDI sind die ganzen Funktionen, die mittels
DLL bereit gestellt werden (z.B. FTD2XX.H) als
FTD2XX_API
FT_STATUS WINAPI FT_GetDriverVersion(
FT_HANDLE ftHandle,
LPDWORD lpdwVersion
);
deklariert.
Das "WINAPI" brachte mich auf die Idee, die Aufrufkonvention von .Cdecl
auf .StdCall zu ändern und schon funktionierte alles klaglos für DotNet
3.5 und auch 4.0.
Tja, eigentlich könnte ich ja jetzt fröhlich weitercodieren. Aber als
der Korinthenkacker, der ich nun mal bin, lässt mir das Ganze keine
Ruhe.
Ich habe auch schon Versuche mit DumpBin.exe auf der DLL gemacht, um
hinter die tatsächlich verwendete Aufrufkonvention zu kommen, aber auch
das brachte mir nichts Aussagekräftiges.
Der Code, den ich oben zitiere, stammt samt und sonders von FTDI.
Sollten die nicht wissen, wie ihre Aufrufkonventionen sind?
Ich hoffe nun auf das Urteil eines Gurus, der mir bestätigen kann, dass
meine Änderung der Aufrufkonvention auf StdCall die richtige Lösung ist.
;-)
Schönen Sonntag noch!
Edgar C. schrieb:> Der Code, den ich oben zitiere, stammt samt und sonders von FTDI.> Sollten die nicht wissen, wie ihre Aufrufkonventionen sind?
Was verbirgt sich denn hinter den Makros in dem Codeschnipsel, expandier
die doch mal um zu sehen was da wirklich steht. Stdcall ist nicht
unüblich unter Windows, um nicht zu sagen es ist der default.
Edgar C. schrieb:> Ich habe auch schon Versuche mit DumpBin.exe auf der DLL gemacht, um> hinter die tatsächlich verwendete Aufrufkonvention zu kommen, aber auch> das brachte mir nichts Aussagekräftiges.
Du musst es disassemblieren und schauen wie die Parameter übergeben
werden und wie der Stack benutzt wird und von wem er aufgeräumt wird.
Hallo,
FTDI have provided a managed .NET wrapper class for the FTD2XX DLL on
the Windows platform.
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate FT_STATUS tFT_GetDriverVersion(IntPtr ftHandle, ref
UInt32 lpdwDriverVersion);
ms
Erst mal vielen Dank an alle!
Die Links, die ihr mir geschickt habt, waren meiner Browserhistorie der
letzten beiden Tage bereits bekannt, trotzdem habe ich noch einmal genau
nachgelesen.
So langsam komme ich zu der Überzeugung, dass StdCall der richtige
Aufruf ist und FTDI sich bei ihrem Beispiel-Code schlicht vertan hat.
Letzte Klarheit würde wohl nur ein Blick in die Sourcen geben (die aber
leider nicht verfügbar sind), da WINAPI und StdCall zwar meist, aber
eben nicht zwangsläufig zusammen gehören. So verstehe ich es jedenfalls.
Oder eben der disassemblierte Code. Dabei habe ich leider gerade eine
Bauchlandung erlitten. Hier ein Schnipsel:
Interessant wäre also, was sich hinter dem call 01222E28 verbirgt.
Tja, leider macht Visual Studio an dieser Stelle einfach kein 'Step
Into', sondern nur ein 'Step Over'. Und wenn man zu der entsprechenden
Zieladresse hochscrollt findet man Gibberish. Ich schätze mal, dass der
Disassembler da aus dem Tritt kommt:
Ich denke, ich werde es jetzt langsam dabei bewenden lassen und nicht
noch tiefer einsteigen, sonst gibt das dieses Jahr nichts mehr mit dem
Wechsel der Glühbirne ;-)
Vielleicht nerve ich FTDIs Support ja noch mit der Frage nach dem
richtigen Aufruf. Bisher waren die zwar immer langsam, aber doch
hilfsbereit.
Euch noch einen schönen Rest-Ersten-Advent!
Edgar C. schrieb:> Letzte Klarheit würde wohl nur ein Blick in die Sourcen geben (die aber> leider nicht verfügbar sind), da WINAPI und StdCall zwar meist, aber> eben nicht zwangsläufig zusammen gehören.
Wozu brauchst Du deren Sourcen, Du hast doch bereits die Header von
FTDI, da steht alles drin was der Compiler wissen müsste um korrekten
Code für den Aufruf der Funktionen zu erzeugen. Du brauchst auch nicht
rumzurätseln was WINAPI hier bedeutet, Du schaust stattdessen einfach
nach wie dieses Makro und die anderen Makros expandieren würden, dann
hast Du Gewissheit.
Hallo Bernd,
ich glaube du hast mich jetzt in die richtige Richtung geschubst.
In die Header-Dateien hatte ich bisher nur per Texteditor reingeschaut,
weil ich sie in meinem eigenen Programm ja gar nicht benutze. C# kennt
ja eigentlich keine Header?
Nur zur Referenz hier mein eigener Code, den ich z.T. aus dem Beispiel
von FTDI extrahiert habe. (Ich bitte um Nachsicht, falls ich da gegen
irgendwelche Regeln der Kunst verstoßen sollte, denn ich stamme noch aus
den Borland-Plain-C-Zeiten)
ABER!!! Natürlich gibt es den Code für die JTAG-DLL von FTDI, sogar als
vollständiges Projekt zum Herunterladen! (Im Gegensatz zu dem Quellcode
für die D2XX.DLL, den ich die ganze Zeit im Kopf hatte)
Ich habe das Projekt also eingeladen und siehe da: