Seite 3 von 5

Re: Delphi DLL

Verfasst: 30.11.2010 15:20
von ts-soft
Galahat hat geschrieben:Ich schmeiß das ding gleich vorm Schneepflug
Naja, Delphi und VB DLLs haben so Ihre Tücken :mrgreen:

Code: Alles auswählen

Prototype USB32IO_OpenDevice(*Par1, *Par2, *Par3, *Par4)

Define.l DevNum

Code: Alles auswählen

@DevNum
als ersten Parameter übergeben

Musste einfach mal probieren :wink:

Re: Delphi DLL

Verfasst: 30.11.2010 15:44
von D.J.Peters
Also ich habe mir die VB und Delphi Deklarationen angesehen
und als alter Hase muss ich mich doch wundern.

Soweit ich es sehe gibt es die DLL im Treiber/XP Verzeichnis
das merkwürdige ist das nicht nur VB und Delphi die selbe DLL benutzen
sondern exakt die selben exportierten Funktionen.

z.B. OpenDevice()

Demnach würde bei VB String der BSTR Datentype verwendet und bei Delphi der DELPHISTRING Datantype.

Was eigentlich so nicht sein kann weil der BSTR vom DELPHISTRING abweicht.

Aber aufgepast da in VB der String BYVAL übergeben wird und nicht BYREF
wird die Addresse des ersten Zeichens übergeben
(das ist nichts anderes als ein *pointer kann daher sogar in PB als long deklariert werden string.l)

Delphi erkennt vermutlich an der DLL/STDCALL Deklaration das ebenfals "nur" ein Zeiger auf das erste Zeichen erwartet wird.

Also übergebe die Addresse des ersten Zeichen es muss nur sichergestellt sein das
das letze Zeichem im String immer eine 0 ist sonst kann die DLL die Länge des Stringes nicht ermitteln.

Grüsse Joshy

Re: Delphi DLL

Verfasst: 30.11.2010 15:49
von Galahat
:allright:

Jetzt schmiert er nicht mehr ab...

Jetzt muss ich erst mal begreifen, was sonst noch nicht ganz stimmt.

mit @Devnum , was eine Art Geräte-ID ist (eigentlich 1 Byte groß), bekomme ich von GetErrorDevice ein 2 zurück, was darauf hindeutet, das der Inhalt wohl >31 ist....kein wunder, wenn er einen Zeiger bekommt

Re: Delphi DLL

Verfasst: 30.11.2010 15:56
von Galahat
@Joshi

Wo lernt man denn sowas ??? :o

Demnach lag ich ja ganz am Anfang mit OPENDEVICE(..., Par1.p-bstr, ...,...) garnicht mal so daneben, oder verstehe ich dich da falsch?

Re: Delphi DLL

Verfasst: 30.11.2010 20:22
von Galahat
Mir ist da was unter die Augen gekommen

Etwas weiter oben erläutert D.J.Peters etwas ganz interassantes. Klingt plausibel, doch das das mit schnoden VB-Strings wohl auch klappt, liegt unter anderem vielleicht auch an der Tatsache, das ein VB-String 1Byte pro Zeichen + 10Byte groß ist, wie ich gerade in meinem alten VB Buch lesen konnte.

Darauf habe ich den ganzen Pointerverwurschtelkram herausgenommen und schlicht Fixed Strings definiert.
Mit gewissem Erfolg. Denn zuvor mochte er nicht mit .s im Prototypen arbeiten...das gab immer heftige Probleme.

Ich frage mich nur, wenn ich einen String bauen möchte mit dem Inhalt EZUSB + NULL + 10Byte, wie baue ich denn das zusammen ?? :coderselixir:

Re: Delphi DLL

Verfasst: 30.11.2010 21:53
von D.J.Peters
Hallo Galahat,
Du kannst meiner kleiner Ausführung ruhig vertrauen.

Wenn in VB:

A$=B$+C$

benutzt wird dan werden wirklich OLE Strings benutzt der heute sogennante BSTR String Datentype.

Da alle WINDOWS OS DLL's in C geschrieben sind z.B. KERNEL32, GDI32, USER32
benutzen alle nicht UNICODE Routienen den C String Datenentype "char *".

Würde man nun mit VB eine OS Funktion aufrufen die einen String füllt und es würde der BSTR
als Parameter übergeben dann würde der BSTR - Descriptor mit den Zeichen überschrieben
und ein "print Param$" würde zwangsläufig zum Segfault Error führen.

Daher deklariert man ihn als CallMe(BYVAL Param as string, BYVAL WieGrossIstDerString as integer)

Nun geht VB hin und läst sich vom BSTR die Addresse geben welche auf das erste Zeichen zeigt
und ruft CallMe() damit auf.

Beispiel:
Dim Param as string
Param="Test"
CallMe(Param,len(Param))

Schön daran zu sehen ist das der BSTR keine 0 als Endterminator benutzt und daher mit LEN() die Länge ermittelt werden muss.

Zurück zu deiner USB DLL:
OpenDevice()

Will nun z.B. den Gerätenamen als String-Addresse haben
aber ohne das Du die länge des Stringes als zusätzlichen Parameter mit angeben must.

Ergo:
Benötigt der string eine 0 als Endemakierung (Terminator)
String = "Hello world" + chr(0)

Schönen Abend noch.

Grüsse Joshy

Re: Delphi DLL

Verfasst: 30.11.2010 22:30
von ts-soft
Das entspricht dann aber einem String in PB. Der wird immer als Pointer übergeben und mit Nullbyte
abgeschlossen (in Unicode mit 2 Nullbytes). Also sollte ein einfaches .s richtig sein, das funktioniert
aber anscheinend nicht.

Gruß
Thomas

Re: Delphi DLL

Verfasst: 01.12.2010 05:37
von D.J.Peters
ts-soft hat geschrieben:Das entspricht dann aber einem String in PB.
Das kann ich auch bestätigen.
Ich kannte nicht den genauen Aufbau eines BP Strings daher habe ich es kurz getestet.

Code: Alles auswählen

#DLLID = 1
Result.l = OpenLibrary(#DLLID,"test01.dll") 
If Result=0
  MessageRequester("ERROR:","can't load 'test01.dll",#PB_MessageRequester_Ok+64)
  End
EndIf

*pFunc = IsFunction(#DLLID, "GETBYTEFROMSTRING@8") 
If *pFunc=0
  MessageRequester("ERROR:","can't find 'GETBYTEFROMSTRING@8'",#PB_MessageRequester_Ok+64)
EndIf
OpenConsole()
test.s ="abcd"
Result = CallFunctionFast(*pFunc,test,0):PrintN(Str(Result))
Result = CallFunctionFast(*pFunc,test,1):PrintN(Str(Result))
Result = CallFunctionFast(*pFunc,test,2):PrintN(Str(Result))
Result = CallFunctionFast(*pFunc,test,3):PrintN(Str(Result))
Result = CallFunctionFast(*pFunc,test,4):PrintN(Str(Result))
Input()  
CloseConsole()   
CloseLibrary(#DLLID)
Byte 0-3 enthält die Zeichen und Byte 4 den 0 Terminator.

Ja Galahat jetzt bist Du an der Reihe.

Stell Dich nicht an und sage Uns doch einfach was Du falsch machst :lol:

Poste doch mal Deinen "bugy" Code und stelle sicher das Du auch die richtige DLL verwendest also die auch für VB vorgesehen ist.

Up's 04:35 wie schnell doch die Zeit am Rechner vergeht.

Gute Nacht / guten Morgen.

Grüsse Joshy

Re: Delphi DLL

Verfasst: 01.12.2010 12:59
von Galahat
So.. mit VB6 hatte ich erfolg, kann also definitiv jetzt die Codes posten. VB6 geht, PB nicht.
Selbe DLL genutzt.

Code: Alles auswählen

'***************VISUAL BASIC 6**************************************************
'IM Modul *
'**********

Declare Function Opendevice Lib "USB32IO.dll"(byval Devnumber As Byte , _
                                               Byval Drivername As String , _
                                               Byval Id As String , _
                                               Byval Keyword As String) As Long

'*************
'In der Form *
'*************
Private Sub Command1_Click()

  Dim DevNum As Byte
  Dim DeviceID As Long
  Dim S0 as String
  Dim S1 as String
  Dim S2 as String 	
  
  S0 = "EZUSB"
  S1 = ""
  S2 = ""

    DeviceID = OpenDevice(DevNum, S0, S1, S2)

    Label1.Caption = DeviceID

End Sub




'________________________ PURE Basic 4.40 _____________________

  Prototype.l USB32IO_OpenDevice(Par1.c, Par2.s,Par3.s, Par4.s)
  
  Global OpenDevice.USB32IO_OpenDevice  
 
  Define.i hdll= OpenLibrary(#PB_Any,"USB32IO.dll")    
  If hdll   
    OpenDevice = GetFunction(hdll, "OpenDevice") 
  Else    
    MessageRequester("Error","Library Error")
  EndIf
  

  Define DevNum.c ;0 bis 31
  Define DeviceID.l  
  
  Define s0.s{255} ; String mit Define und {..}, sonst gehts garnicht
  Define s1.s{255}
  Define s2.s{255}


  S0="EZUSB"
  S1=""
  S2=""

  DevNum = 20

    DeviceID = OpenDevice(DevNum,s0,s1,s2)    
    Debug "Device ID  "  + Str(DeviceID)    

Re: Delphi DLL

Verfasst: 01.12.2010 15:12
von D.J.Peters
Ich habe kein PB4.x aber das hier wäre mit PB 3.xx ok

Code: Alles auswählen

#DLLID = 1
Result.l = OpenLibrary(#DLLID,"USB32IO.dll") 
If Result=0
  MessageRequester("ERROR:","can't load 'USB32IO.dll' ",#PB_MessageRequester_Ok+64)
  End
EndIf

*pFunc = IsFunction(#DLLID, "OpenDevice") 
If *pFunc=0
  MessageRequester("ERROR:","can't find 'OpenDevice'",#PB_MessageRequester_Ok+64)
EndIf


DevNumber.b   = 0
DriverName.s  = "EZUSB"
Id.s          = ""
KeyWord.s     = ""

DeviceId.l  

OpenConsole()

DeviceId = CallFunctionFast(*pFunc,DevNumber,DriverName,Id,KeyWord)
PrintN(Str(DeviceId))

PrintN("press any key for quit ...")
Input()  
CloseConsole()   
   
CloseLibrary(#DLLID)
Was auch noch sein kann !
Sollte PB für DevNumber wirklich nur ein Byte auf dem Stack "pushen" dann kann es auch nicht gehen.
Denn auch ein Byte muss 4 Bytes auf dem Stack belegen.

Das kannst du aber leicht testen in dem Du DevNumber so DevNumber.L deklarierst.

Viel Erfolg.

Grüsse Joshy