SDK-Helfer/ Tools | | | | - Seite 1 - |
| Jens-Arne Reumschüssel | Guten Abend zusammen,
ich bin kürzlich über das Problem gestolpert, dass XPSE eine ziemlich große Quelldatei von mir nicht mehr verarbeiten konnte. Variablen wurden plötzlich als nicht definiert gemeldet und andere "erratische" Probleme mehr. Ich könnte mir vorstellen, dass dies daran liegt, dass XPSE Schlüsselworte in Windows-Atoms verwaltet. Da ist irgendwann Schluss (bei irgendwas zwischen 60.000 und 70.000 Stück, wobei man bedenken muss, dass XPSE die Windows-API mit vorhält). Vielleicht ist es aber auch etwas ganz anderes, ich kann ja nicht in den "Maschinenraum" von XPSE schauen.
Jedenfalls blieb mir, da XPSE nicht mehr gepflegt wird, nichts anderes übrig, als das nachzubauen. Das Ergebnis ist JRPC3.
----- Features:
*vernünftige Meldung von Fehlern *direkte Anzeige des Programmablaufes in XProfEd (sofern der unten erhältliche aufgebohrte XProfEd verwendet wird) *Umsetzung der alten Profan-Syntax für Operatoren und alte Containerfunktionen *extrem schnelle native fbPROCs, sofern man FreeBasic installiert hat (kostenlos, siehe Hilfe) *mit fbPROCs kann zudem Inline-Assembler auch vor XProfan X4 realisiert werden *extrem schnelle native pbPROCs, sofern man PureBasic installiert hat *Echtzeitverfolgung von Variableninhalten *einfache Zeitmessungen im Programmablauf *Profan-Kompilerdirektiven funktionieren endlich vernünftig (z.B. Verschachtelung) *eingebettete Variablen funktionieren auch mit Arrays *die meisten WIN32-API-Funktionen sind bereits vordefiniert mitgeliefert *API-Aufrufe über @external(...) werden automatisch in @call(...)-Aufrufe umgesetzt *Einrückungsanalyse zum Finden von vertrackten Verschachtelungsfehlern *Klammeranalyse zum Finden von vertrackten Klammerfehlern *ENUMERATE-Funktionalität *Assert zur Fehlerkontrolle *es können beliebige DLLs in die XProfan-EXE integriert werden, sodass sie nicht mit ausgeliefert werden müssen (siehe {$WrapDll}) *einfaches Killen von mit JRPC3 gestarteten Programmen (interpretiert, .prc gestartet, .exe gestartet) *extrem schnell (und daher natürlich nicht in XProfan geschrieben, da eine interpretierte Sprache hierfür naturgemäß viel zu langsam ist) *beim Start von JRPC3 bereits vorhandene .prc-Dateien können zum Starten und Linken genutzt werden (es wird ein Hinweis angezeigt, dass es sich um ein altes Kompilat handelt) *der Profan-Compiler kann zur Beschleunigung mit hoher Prozessorpriorität aufgerufen werden *eingebauter Update-Checker mit Download, falls es ein Update gibt (Hilfe --> online nach Updates suchen) *64- oder 32-bit-Version verfügbar (einfach JRPC3_64.exe oder JRPC_32.exe als Interpreter in XProfEd hinterlegen [Optionen --> Allgemeine Einstellungen] und JRPC3 mit F7 starten) - Achtung, die 64-bit-Version erzeugt natürlich keine 64-bit-XProfan-Programme, da XProfan das nicht kann, sondern JRPC3 selbst wird als 64-bit-Programm ausgeführt *XProfan X4-Syntax verfügbar (möglicherweise noch nicht alles, da ich vermutlich nicht alles davon benutze, aber ich habe mich um Vollständigkeit bemüht - jedenfalls sind z.B. HASH-Arrays und QUADINTs dabei) *Interpreter, PRCs und EXEs können mit Kommandozeilenparametern ausgeführt werden *Interpreter, PRCs, EXEs und XPSE können mit Administratorrechten ausgeführt werden *Prozeduren, die in dem aktuellen Programm zwar enthalten sind, aber nicht verwendet werden, werden aus der umgesetzten Datei entfernt, um die Dateigröße des Kompilats möglichst klein zu halten *Variablen, die in dem aktuellen Programm zwar enthalten sind, aber nicht verwendet werden, werden aus der umgesetzten Datei entfernt, um die Dateigröße des Kompilats möglichst klein zu halten und den Speicherverbrauch zu optimieren *nPROCs aus XPSE werden automatisch mit XPE zu einer DLL umgesetzt und die Aufrufe der nPROCs im Programm entsprechend angepasst, sofern XPSE vorhanden ist *fast alles aus XPSE funktioniert auch in JRPC3 ({$NOERR}, {$(PRE)BATCH}, {$PUSHKEYWORD}, Interpreter, Runtime und Compiler festlegen, Shorties, ...) *XProfEd_JR mit Quelltext-AutoComplete *XProfEd_JR mit Quelltext-Memory-Funktion (Markierungen, zu denen zurückgesprungen werden kann)
Einschränkungen: -kein XPSE-Inline-Assembler, wohl aber XProfan-Inline-Assembler (darin allerdings keine Prüfungen auf Korrektheit des Codes) -ABER: man kann XPSE aus JRPC3 heraus aufrufen, sodass diese Funktionalität weiterhin verfügbar ist, sofern man XPSE besitzt (neuer Shorty: {$x}) -Variablen, die in einer Prozedur nicht deklariert sind, sondern "aus der aufrufenden Prozedur übernommen werden", sind standardmäßig nicht zugelassen (XProfan erlaubt das, aber so etwas ist genauso tödlich wie GOTO-Anweisungen). Bitte alle zu nutzenden Inputs als Parameter übergeben, und wenn etwas aus dem aufrufenden Programmteil verändert werden muss, beim Aufruf als Parameter z.B. @addr(x&) verwenden und in der Prozedur parameters x# und LONG x#,0=y& nutzen. Wenn man aber unbedingt "vererbte" Variablen nutzen möchte, kann man dies mit der Kompilerdirektive {$Declare...} tun.
*als Hommage an XPSE lautet die Endung der Ausgabedatei ".enh3"
Eine genauere Erläuterung der einzelnen Features ist der chm-Hilfedatei zu entnehmen, die im Programm unter Hilfe --> Hilfedatei anzeigen oder mit F1 verfügbar ist.
----- /Features
Herunterladen und installieren: JRPC3 kann unten heruntergeladen werden (setup_jrpc3.exe oder als ZIP-Datei). Als Installationsverzeichnis bitte das XProfan-Stammverzeichnis angeben, also dasjenige, in dem die Dateien PROFAN.EXE, PROFCOMP.EXE, PRFRUN32.EXE etc. liegen. Alternativ kann die ZIP-Datei heruntergeladen und deren Inhalt manuell ins XProfan-Stammverzeichnis kopiert werden.
Einrichtung: JRPC3_64.exe oder JRPC_32.exe als Interpreter in XProfEd hinterlegen [Optionen --> Allgemeine Einstellungen] und JRPC3 mit F7 starten.
Alle Befehle sind mit dem Befehl "h" wie "Hilfe" abrufbar und sollten selbsterklärend sein.
Für viele erweitere Features, die XProfEd betreffen, wie z.B. jenes, die Zeile, in der ein Fehler auftrat, direkt in XProfEd anzeigen zu können, ist der mitinstallierte XProfEd_JR erforderlich. Dafür muss man also XProfEd_JR.exe statt XProfEd.exe als Editor benutzen. Als "goody" gibt es dazu, dass beim Auf- und Zufalten von Programmen ein Fortschrittsanzeiger integriert ist (das kann bei großen Programmen ja bekanntlich ein bisschen dauern).
Es mag sein, dass noch nicht alles perfekt funktioniert. Ich bitte hierfür um Nachsicht. Meine Programme lassen sich umsetzen, aber das muss noch lange nicht heißen, dass dies mit Programmen anderer Autoren, die jeder so ihre Eigenheiten haben, auch funktioniert.
Fehlermeldungen und Verbesserungsvorschläge gerne an jreumsc@web.de oder hier im Forum.
Beste Grüße, Jens-Arne |
| 2.584 kB | | Bezeichnung: | JRPC3 | | Version: | 10.29 | | Kurzbeschreibung: | JRPC3-Installer | | Hochgeladen: | 15.02.2021 | | Ladeanzahl: | | | | Herunterladen | | | | 1.699 kB | | Bezeichnung: | XProfEd_JR | | Version: | 5.2 | | Kurzbeschreibung: | Alte Version ohne AutoComplete zur Sicherheit | | Hochgeladen: | 15.02.2021 | | Ladeanzahl: | | | | Herunterladen | | | | 3.777 kB | | Bezeichnung: | JRPC3 | | Version: | 10.29 | | Kurzbeschreibung: | ZIP-Datei statt Installer | | Hochgeladen: | 02.04.2021 | | Ladeanzahl: | | | | Herunterladen |
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 16.02.2021 ▲ |
| |
| | | | - Seite 23 - |
| | « Dieser Beitrag wurde als Lösung gekennzeichnet. » | | - Seite 15 - |
| Jens-Arne Reumschüssel | Es gibt eine neue Version, die anders mit dem internen Messagehandling umgeht. Bitte probier die mal aus. Vielleicht ist das Problem damit behoben. |
| | | XProfan X4XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 24.09.2022 ▲ |
| | |
| | funkheld | Wie wird das bitte in Pb umgesetzt?
nProc getCircP(long r,w) return long(sin(0.0174532925199433*float(w)/1000.0)*float(r)) endproc
Danke. Gruss |
| | | | |
| | Jens-Arne Reumschüssel | Ich denke, so:
declare r!,w!
pbProc getCircP(*r,*w) protected r.d,w.d r=PeekD(*r) w=PeekD(*w) procedurereturn sin(0.0174532925199433*w/1000.0)*r endproc
cls r!=2 w!=3 print getCircP(@addr(r!),@addr(w!)) waitinput end
Aber ist es wirklich sinnvoll, einen Integerwert zurückzugeben? Sollte das nicht besser auch ein Float sein? So etwa:
declare r!,w!,result!
pbProc getCircP(*r,*w,*result) protected r.d,w.d r=PeekD(*r) w=PeekD(*w) PokeD(*result,sin(0.0174532925199433*w/1000.0)*r) endproc
cls r!=2 w!=3 getCircP(@addr(r!),@addr(w!),@addr(result!)) print result! waitinput end
Oder noch einfacher mit Shared-Variablen:
declare r!,w!,result! shared
pbProc getCircP() result!=sin(0.0174532925199433*w!/1000.0)*r! endproc
cls r!=2 w!=3 getCircP() print result! waitinput end
|
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 14.05.2023 ▲ |
| |
| | funkheld | Danke für deine schnelle Hilfe.
Werde es noch einmal testen.
Danke. |
| | | | |
| | Walter | Freue mich über JRPC3, habe nun aber ein Problem mit einem array. JRPC3_64.exe läuft problemlos durch, der nachfolgend gestartete Interpreter bricht jedoch ab mit "Das Element gibt es nicht!".
Wenn ich das Programm gleich im Profan-Interpreter starte, läuft es problemlos durch.
' Array-Test / Shuffle
' Mischt die Einträge der Listboxliste
cls
randomize
' Listboxliste mit Strings füllen
clearlist
addstring(0,"BlaBla1")
addstring(0,"BlaBla2")
addstring(0,"BlaBla3")
addstring(0,"BlaBla4")
addstring(0,"BlaBla5")
listbox$("Start",1)
shuffle()
listbox$("Ergebnis",1)
end
'---------------------
proc shuffle
'---------------------
' Mischt die Einträge der Listboxliste
declare anz%
anz%=getcount(0)
Declare i%,nr%,L$[anz%]
clear L$[]
i%=0
While i% < anz%' Durch die Listboxliste
nr%=rnd(anz%)' Einen zufälligen Platz im Array wählen
while L$[nr%]<>""' schon besetzt? Dann den nächsten freien Platz suchen
inc nr%
case nr%=anz%: nr%=0' falls am Ende: von vorne weg neu probieren
wend
L$[nr%]=getstring$(0,i%)
Inc i%
wend
clearlist
move("ArrToList",L$[])
endproc' shuffle
Woran liegt das? |
| | | | |
| | Jens-Arne Reumschüssel | Das hatte etwas damit zu tun, dass Du ein Array über eine Variable dimensioniert hast (Declare ...,L$[anz%]). In diesem Fall müssen kurze Variablennamen und immer global definierte Variablen in JRPC3 ausgeschaltet werden, was nun automatisch geschieht. Jetzt sollte Dein Programm also laufen. |
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 15.05.2023 ▲ |
| |
| | Walter | | | | | |
| | Jens-Arne Reumschüssel | Version 9.08a:
Map-Daten erzeugen: Fehler, die während der Umsetzung eines Codes mit JRPC3 festgestellt werden, werden bekanntlich direkt von JRPC3 an der richtigen Stelle im Quellcode angezeigt (wenn der mitglieferte XProfEd_JR genutzt wird). Wenn allerdings zur Laufzeit eines Programmes ein Fehler auftritt (z.B. eine Überschreitung des Dimensionierungsbereichs eines Arrays), gibt XProfan nur eine knappe Laufzeit-Fehlermeldung aus, die aber oft wenigstens eine Zeilennummer enthält. Diese Zeilennummer bezieht sich jedoch leider auf den kumulierten Code, den XProfan abarbeitet, sodass es fast unmöglich ist, die ausgegebene Zeilennummer einer Zeilennummer im Quelltext und dazu auch noch der richtigen Quelltextdatei (z.B. einer INC-Datei) zuzuordnen. Hierbei helfen Map-Daten. Wenn diese Option aktiviert ist, schreibt JRPC3 mit, woher jede einzelne Zeile des Endcodes in der .enh3-Datei stammt, sodass die kumulierten Zeilennummern wieder ihrem Ursprung zugeordnet werden können. Wenn ein XProfan-Laufzeitfehler mit einer darin gemeldeten Zeilennummer auftritt, kann man nun über das Menü "Datei" --> "Laufzeitfehlerzeile finden" die von XProfan ausgegebene Zeilennummer eingeben und erhält in XProfEd_JR die Zeile aus der richtigen Quelldatei angezeigt, in der der Fehler auftrat. Das funktioniert allerdings nur, wenn vorher in den Optionen von JRPC3 die Map-Daten-Erzeugung aktiviert wurde. Dies kann auch noch nach Auftreten des Laufzeitfehlers geschehen, sofern der Programmcode nicht ergänzt oder gekürzt wurde, was natürlich die ermittelte Zeilennummer beeinflussen würde. Wenn die Map-Daten gerade nicht mehr gebraucht werden, sollte diese Option wieder deaktiviert werden, weil sie den Quelltext um extrem viele Kommentare erweitert und damit den Interpreter von XProfan langsamer macht. |
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 16.05.2023 ▲ |
| |
| | Jens-Arne Reumschüssel | Hier ein ausführliches Beispiel für die Nutzung von fbPROCs für das schnelle Vorgeben von beliebig vielen vordefinierten Wörtern in Edit-Controls. Die Vorgaben stehen jeweils in einer GridBox, wobei für verschiedene Edit-Controls unterschiedliche GridBoxen verwendet werden können. Es werden fbPROCs verwendet, damit nicht nur diejenigen, die PureBasic besitzen, das ausprobieren können.
Ganz am Anfang in FBGLOBAL bei #include muss der jeweils zutreffende Pfad angegeben werden. Denn es wird die Bibliothek commctrl.bi gebraucht, um die API-Konstanten für ListViews benutzen zu können.
declare _hE%,_hE2%,_hGB%,_hGB2%,_ende%,_s$,_ws#
'{ 'fbPROCs FBGLOBAL #include "D:\Programme\FreeBasic\inc\win\commctrl.bi" 'hier muss der richtige Pfad angegeben werden dim shared as integer _MaxNum=0,_MinLaenge=1 redim shared as integer _NumhGB(0 to 1) redim shared as string _OldAktEntry(0 to 1) dim shared as string _KeywordEnders _KeywordEnders=" .,:-+*/\!;" ENDFBGLOBAL
fbPROC AmendEditText(byval hE as integer,byval hGB as integer,byval CaseSensitive as integer) as integer export dim as byte pointer pAktEntry dim as string AktEntry,Vorgabe,s2,AktSubStr,LeftPart,RightPart dim as integer i,CurPos,erg,num dim as zstring pointer zs,zs2 '{ 'Nummer der GB ermitteln num=0 for i=1 to _MaxNum if _NumhGB(i)=hGB num=i exit for endif next i if num=0 _MaxNum=_MaxNum+1 num=_MaxNum redim preserve _NumhGB(0 to num) redim preserve _OldAktEntry(0 to num) _NumhGB(num)=hGB _OldAktEntry(num)="" endif '} '{ 'aktuellen Eintrag ermitteln pAktEntry=allocate(10001) sendmessage(cast(handle,hE),WM_GETTEXT,10000,cast(integer,pAktEntry)) AktEntry=Peek(zstring,pAktEntry) deallocate(pAktEntry) '} if AktEntry<>_OldAktEntry(num) if len(AktEntry)>len(_OldAktEntry(num)) CurPos=loword(sendmessage(cast(handle,hE),EM_GETSEL,0,0)) '{ 'aktuellen Substring ermitteln AktSubStr="" for i=CurPos to 0 step -1 if i>0 if instr(_KeywordEnders,mid(AktEntry,i,1))<>0 LeftPart=left(AktEntry,i) exit for else AktSubStr=mid(AktEntry,i,1)+AktSubStr endif else LeftPart="" endif next i for i=Curpos+1 to len(AktEntry) if instr(_KeywordEnders,mid(AktEntry,i,1))<>0 RightPart=right(AktEntry,len(AktEntry)-(i-1)) exit for else AktSubStr=AktSubStr+mid(AktEntry,i,1) endif next i '} if len(AktSubStr)>=_MinLaenge i=LVFindText(hGB,AktSubStr,-1) if i>=0 Vorgabe=LVGetText(hGB,i) if CaseSensitive if left(Vorgabe,len(AktSubStr))=AktSubStr erg=1 else erg=0 endif else if ucase(left(Vorgabe,len(AktSubStr)))=ucase(AktSubStr) erg=1 else erg=0 endif endif if erg if len(AktSubStr)<>len(Vorgabe) s2=LeftPart+Vorgabe+RightPart zs=Allocate(len(s2)+1) poke zstring,zs,s2 sendmessage(cast(handle,hE),WM_SETTEXT,0,cast(integer,zs)) sendmessage(cast(handle,hE),EM_SETSEL,len(LeftPart)+len(AktSubStr),len(LeftPart)+len(Vorgabe)) deallocate(zs) endif endif endif endif endif _OldAktEntry(num)=AktEntry endif return 0 ENDPROC 'AmendEditText
fbPROC SetMinLaenge(byval Laenge as integer) as integer export _MinLaenge=Laenge if _MinLaenge<1 _MinLaenge=1 endif return 0 ENDPROC 'SetMinLaenge
fbPROC SetKeywordEnders(byval Text as zstring pointer) as integer export _KeywordEnders=peek(zstring,Text) return 0 ENDPROC 'SetKeywordEnders
'{ 'Hilfsfunktionen fbPROC LVGetCount(byval hLV as integer) as integer return sendmessage(cast(any pointer,hLV),LVM_GETITEMCOUNT,0,0) ENDPROC 'LVGetCount fbPROC LVFindText(byval hLV as integer,byval text as string,byval StartLine as integer) as integer 'search is case insensitive dim as LVFINDINFOA LVFI dim as zstring pointer zs dim as integer erg LVFI.flags=LVFI_PARTIAL OR LVFI_STRING zs=allocate(len(text)+1) poke zstring,zs,text LVFI.psz=zs erg=sendmessage(cast(any pointer,hLV),LVM_FINDITEM,StartLine,cast(integer,@LVFI)) deallocate(zs) return erg ENDPROC 'LVFindText fbPROC LVGetText(byval hLV as integer,byval Zeile as integer,byval Spalte as integer=0) as string dim as LVITEM LVI dim as string ret,s dim as zstring pointer LVItemText 'LVI=mask&,iItem&,iSubItem&,state&,stateMask&,pszText&,cchTextMax&,iImage&,lParam&,iIndent&,iGroupId&,cColumns&,puColumns&,piColFmt&,iGroup& LVItemText=Allocate(2001) LVI.iItem=Zeile LVI.iSubItem=Spalte LVI.mask=LVIF_TEXT LVI.pszText=LVItemText LVI.cchTextMax=2000 sendmessage(cast(any pointer,hLV),LVM_GETITEMTEXT,Zeile,cast(integer,@LVI)) ret=peek(zstring,LVItemText) deallocate(LVItemText) return ret ENDPROC 'LVGetText '} '}
'*** Hauptprogramm WindowStyle 1+2+4+8+512 cls _hE%:=@create("EDIT",%HWnd,"",10,10,300,20) dim _ws#,1000 widestring _ws#,0="Automarken" @sendmessage(_hE%,~EM_SetCueBanner,0,_ws#) 'lParam: 0=Hinweis nur anzeigen, wenn das Editfeld nicht den Fokus hat (default); 1=auch anzeigen, wenn fokussiert _hE2%:=@create("EDIT",%HWnd,"",10,40,300,20) widestring _ws#,0="rund um den Fernseher" @sendmessage(_hE2%,~EM_SetCueBanner,0,_ws#) 'lParam: 0=Hinweis nur anzeigen, wenn das Editfeld nicht den Fokus hat (default); 1=auch anzeigen, wenn fokussiert dispose _ws# _hGB%:=@create("GRIDBOX",%HWnd,"1;0;0",1,0,0,0,0) 'sortiert, damit Einträge alphabetisch sortiert vorgegeben werden @sendmessage(_hGB%,~WM_SETREDRAW,0,0) 'beschleunigt das Füllen der Gridbox deutlich, außerdem ist sie sowieso unsichtbar @addstring(_hGB%,"BMW"):@addstring(_hGB%,"Audi"):@addstring(_hGB%,"VW"):@addstring(_hGB%,"Skoda"):@addstring(_hGB%,"Nissan") @addstring(_hGB%,"Honda"):@addstring(_hGB%,"Chevrolet"):@addstring(_hGB%,"Mini"):@addstring(_hGB%,"Mercedes") @addstring(_hGB%,"Opel"):@addstring(_hGB%,"Alfa"):@addstring(_hGB%,"Romeo"):@addstring(_hGB%,"Aston"):@addstring(_hGB%,"Martin") @addstring(_hGB%,"Bentley"):@addstring(_hGB%,"Bugatti"):@addstring(_hGB%,"Buick"):@addstring(_hGB%,"Cadillac"):@addstring(_hGB%,"Chrysler") @addstring(_hGB%,"Citroen"):@addstring(_hGB%,"Dacia"):@addstring(_hGB%,"Daihatsu"):@addstring(_hGB%,"Dodge") _hGB2%:=@create("GRIDBOX",%HWnd,"1;0;0",1,0,0,0,0) 'sortiert, damit Einträge alphabetisch sortiert vorgegeben werden @sendmessage(_hGB2%,~WM_SETREDRAW,0,0) 'beschleunigt das Füllen der Gridbox deutlich, außerdem ist sie sowieso unsichtbar @addstring(_hGB2%,"Fernseher"):@addstring(_hGB2%,"Programm"):@addstring(_hGB2%,"Programmzeitschrift"):@addstring(_hGB2%,"Serie") @addstring(_hGB2%,"Sender"):@addstring(_hGB2%,"Fernbedienung") usermessages $10 SetMinLaenge(1) 'minimale Länge des eingegebenen Textfragments, ab der die Vorgaben hinzugefügt werden _s$=" " SetKeywordEnders(@addr(_s$)) 'nur " " als Endzeichen für Suchstrings definieren (default=" .,:-+*/\!;") @setfocus(%HWnd) _ende%=0 whilenot _ende% waitinput AmendEditText(_hE%,_hGB%,0) '0=case insensitive, 1=case sensitive AmendEditText(_hE2%,_hGB2%,0) '0=case insensitive, 1=case sensitive if @iskey(27) or (%uMessage=$10) _ende%=1 while @iskey(27) sleep 25 endwhile endif endwhile end
|
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 21.05.2023 ▲ |
| |
| | Walter | Habe leider wieder ein Problem: Verwende hashes.dll, um für eine Datei die MD5-Prüfsumme zu berechnen. [...] Geprüft wird einfach irgendein Text in der Datei Prüfdatei.txt. Funktioniert mit dem normalen Interpreter problemlos - mit JRPC3 gibt es allerdings ein No Return beim Start des Interpreters mittels i (auch, wenn ich {$NoLocal2GlobalVarConversion} verwende).
' Test von hashes.dll
{$NoLocal2GlobalVarConversion}
declare Dat$,dll2&,Pfad$
cls
Pfad$=GetDir$("")
dll2&=UseDLL(Pfad$+"\\hashes.dll")
DEF testit(3) ! "hashes.dll","testit"
' Prüfdatei
Dat$=Pfad$+"\\Prüfdatei.txt"
'
Prüfsumme(Dat$)
'
FreeDLL dll2&
end
'---------------------
proc Prüfsumme
'---------------------
' Berechnen der Prüfsumme einer Datei mittels MD5.pcu
parameters Prüfdatei$
declare T&,T$,Datei$
Datei$ = Prüfdatei$' Hier muss durch eine lokale Variable eine lokale Adresse erzeugt werden
' in die Datei "MD5" wird der MD5 reingeschrieben
' der steht aber auch in t$
t& = testit(addr(Datei$),"MD5",chr$(0))
t$ = string$(t&,0)
' MD5 der Datei steht auch in t$
messagebox(t$,"MD5",0)
endproc' Prüfsumme
|
| | | | |
| | Jens-Arne Reumschüssel | Hallo Walter,
hier ist das "chr$(0)" beim Funktionsaufruf von testit(...) das Problem. JRPC3 erzeugt standardmäßig einen external-Aufruf. Da funktioniert die Typumwandlung von Strings in String-Adressen für chr$(...) von XProfan offenbar nicht, bei der DEF-Definition aber schon. Es ist an dieser Stelle übrigens relativ sinnfrei, chr$(0) zu benutzen, weil daraus binär exakt 0 wird. Schreibe also:
t& = testit(addr(Datei$),"MD5",0)
Dann funktioniert es auch mit JRPC3.
Wenn Du das chr$(0) beibehalten willst, kannst Du die Umwandlung von DEF-Funktionen in external-Funktionen auch ausschalten: {$NoDef2ExternalConversion}
Um das Grundproblem zu verstehen, muss man wissen, dass die Parameter von DLLs *immer* 4 Bytes breit sind (in 32bit-Programmen). Also ist auch der Parameter "MD5" eigentlich völlig unbrauchbar. Er ist zwar zufällig auch 4 Bytes breit (drei Buchstaben und das Nullbyte am Ende), aber im binären Sinne kommt dabei nichts Sinnvolles heraus. Die DLL erwartet nämlich einen Pointer auf einen String (welcher 4 Bytes breit ist), weil man Strings selbst halt nicht als DLL-Parameter verwenden kann. XProfan wandelt diesen Parameter aber intern in sowas wie @addr(»String, in dem "MD5" steht«) um, deshalb merkt man diesen Programmierfehler normalerweise nicht. Nur für @chr$(...) scheint diese Umwandlung jedenfalls bei external-Aufrufen nicht zu funktionieren, wie oben schon erwähnt.
{$NoLocal2GlobalVarConversion} wird in diesem Beispiel übrigens in keiner Variante gebraucht.
Gruß, Jens-Arne |
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 21.05.2023 ▲ |
| |
| | Walter | | | | | |
| | Jens-Arne Reumschüssel | Ich habe mir jetzt den Funktionsaufruf der DLL nochmal genauer angesehen. In der readme-Datei steht:
?_Hash(Datei$ | bereich#,Algorithmus$[[,start&],size&])
Die Funktion "testit" wird nicht beschrieben, sie ist aber die einzige Funktion, die die DLL exportiert. Vermutlich ist der letzte Parameter "start&", denn sonst würde "0" keinen Sinn machen. In diesem Fall wäre eine Typumwandlung von chr$(0) in einen String-Pointer auf einen String mit einem Null-Byte tödlich, weil da irgendein riesiger Integerwert rauskommen würde (eben die Adresse auf den String). Eine Integer-Zahl wie "0" scheint daher die einzig sinnvolle Variante zu sein. Warum es mit DEF trotzdem funktioniert, ist mir ein Rätsel.
Vielleicht ist es genau andersherum: bei DEF wird nicht in einen String-Pointer umgewandelt, bei external schon. Wie auch immer, da sollte ein numerischer Wert stehen, kein String.
Gruß, Jens-Arne |
| | | XProfan X4 * Prf2Cpp * XPSE * JRPC3 * Win11 Pro 64bit * PC i7-7700K@4,2GHz, 32 GB RAM PM: jreumsc@web.de | 21.05.2023 ▲ |
| |
|
AntwortenThemenoptionen | 62.928 Betrachtungen |
ThemeninformationenDieses Thema hat 8 Teilnehmer: |