Page 1 of 1
callback procedure in Exe
Posted: Thu Oct 11, 2018 7:37 pm
by HPW
Hello,
For the newlisp-interpreter I need a callback into the purebasic Exe.
I had done this from Delphi by this way:
Delphi procedure in Exe:
Code: Select all
procedure TForm1.xRefresh1(param1 : PChar); stdcall;
begin
showmessage('Delphi xRefresh1: '+param1);
end;
With passing the Pointer "integer(@TForm1.xRefresh1)" to the Dll, the Dll is able to call that function from outside the Exe.
This was using the Ansi-version of the Dll s the Pchar works there.
In purebasic I tried:
Code: Select all
Procedure CallBack1(CallBackParam.p-utf8)
MessageRequester("Test", "Test; "+CallBackParam)
EndProcedure
But the p-utf8 pseudo-typ throws an error: Structure not found: p
How do I define for a UTF-8 encode parameter?
So can I specify a procedure in purebasic and call it by its memory adress?
And how do I get the pointer of a purebasic procedure? *CallBack1 ??
Regards
Hans-Peter
Re: callback procedure in Exe
Posted: Fri Oct 12, 2018 9:42 am
by Thorium
You can use Prototype to define a procedure with a pointer to it, you can change at any time.
You get the pointer to a procedure with an @ like this *Pointer = @ProcedureName()
Re: callback procedure in Exe
Posted: Fri Oct 12, 2018 4:25 pm
by HPW
Hello,
Thanks for the tip. I will give it a try.
Regards
Re: callback procedure in Exe
Posted: Fri Oct 12, 2018 11:21 pm
by HPW
Hello,
I tested several version without luck.
Code: Select all
Prototype CallBackStrProto(param.p-utf8)
Procedure CallBack1(CallBackParam.CallBackStrProto)
; theString.s = PeekS(CallBackParam,-1,#PB_UTF8)
; MessageRequester("CallBackDemo", "Param; "+ theString)
MessageRequester("CallBackDemo", "Param; ")
EndProcedure
or
Code: Select all
Prototype CallBackStrProto(param.p-utf8)
Procedure CallBack1(*CallBackParam.CallBackStrProto)
; theString.s = PeekS(CallBackParam,-1,#PB_UTF8)
; MessageRequester("CallBackDemo", "Param; "+ theString)
MessageRequester("CallBackDemo", "Param; ")
EndProcedure
or
Code: Select all
Prototype CallBackStrProto(param.p-utf8)
ProcedureDLL CallBack1(*CallBackParam.CallBackStrProto)
; theString.s = PeekS(CallBackParam,-1,#PB_UTF8)
; MessageRequester("CallBackDemo", "Param; "+ theString)
MessageRequester("CallBackDemo", "Param; ")
EndProcedure
Import of the callback (seems to work)
Code: Select all
Prototype newlispCallbackStrProto(input.p-utf8, callbackaddress.i , calltype.p-utf8 )
newlispCallbackStr.newlispCallbackStrProto = GetFunction(0, "newlispCallback")
MessageRequester("Debug", "CallBackAdress: "+ @CallBack1)
MessageRequester("Debug", "ExeAdress: "+ @hpwNewLisp)
newlispCallbackStr("foo", @CallBack1 ,"stdcall")
newlispEvalStr("(setq MainModulAdress " + @hpwNewLisp + ")")
Programm starts and when I eval foo I get the symbol returen as expected and when I eval MainModulAdress I get the integer from the debug message.
But when I call the callback function itself I get:
Code: Select all
[00:01:41] [ERROR] hpwNewLisp.pb (Zeile: 60)
[00:01:41] [ERROR] Illegale Anweisung. (Ausführen von binären Daten?)
Translation: Illegal code. Execution of binary data
Without Debugger it crashes.
Regards
Re: callback procedure in Exe
Posted: Sat Oct 13, 2018 2:46 pm
by spikey
Help wrote:The pseudotypes can only be used with prototypes, interfaces and imported functions.
That's why you can't get them to work with a procedure declaration - they were never intended to.
A PCHar is a pointer to a string, so this should work providing the prototype of the function import you show is correct.
I can't test it to be sure though.
Code: Select all
ProcedureDLL CallBack1(*CallBackParam)
theString.s = PeekS(CallBackParam, -1, #PB_UTF8)
MessageRequester("CallBackDemo", "Param; " + theString)
EndProcedure
Re: callback procedure in Exe
Posted: Sat Oct 13, 2018 4:06 pm
by HPW
Hello Spikey,
Thanks for the advise. I had tried it because Thorium gave that advice.
But your version thows the same error:
Code: Select all
[16:54:05] [ERROR] hpwNewLisp.pb (Zeile: 60)
[16:54:05] [ERROR] Illegale Anweisung. (Ausführen von binären Daten?)
Translation: Illegal code. Execution of binary data
Without Debugger it crashes.
So remainig questions:
Can a purebasic.exe use ProcedureDLL ?
Can I call a purebasic Procedure from outside using its @-Adress-pointer with compatibel params?
Can a real purebasic made dll callback into a purebasic exe? Had someone does this?
Regards
Re: callback procedure in Exe
Posted: Sat Oct 13, 2018 5:15 pm
by spikey
My apologies - I meant to include this link but I managed to forget it...
viewtopic.php?f=12&t=52807
Like I said - I
think this will work but I can't test to be certain.
Re: callback procedure in Exe
Posted: Sat Oct 13, 2018 8:04 pm
by HPW
Hello Spikey,
Thanks again for the Link.
Reads promissing.
Do not really understand what is done there, but we want to learn. Inline-Assembler is new to me.
Import "/EXPORT:CallBack1" : EndImport
!public _Procedure16 as 'CallBack1'
ProcedureDLL CallBack1(*CallBackParam)
theString.s = PeekS(CallBackParam,-1,#PB_UTF8)
MessageRequester("CallBackDemo", "Param; "+ theString)
EndProcedure
The compiler pops up a message-window:
PureBasic.asm [202]:
public _Procedure16 as 'CallBack1'
error: undefined symbol '_Procedure16'
So this seems all not to be easy supported and quite a hack.
Would be nice if purebasic could support this in a clean manner.
In delphi or pdscript this works without any further work only with the pointer.
Regards
Re: callback procedure in Exe
Posted: Sun Oct 14, 2018 10:07 am
by HPW
Slow progress but still errors.
With advice from the german forum I have this now:
Code: Select all
Procedure CallBack1(*CallBackParam)
theString.s = PeekS(*CallBackParam,-1,#PB_UTF8)
MessageRequester("CallBackDemo1", "Param; "+ theString)
EndProcedure
Code: Select all
MessageRequester("Debug", "CallBackAdress: "+ @CallBack1())
newlispCallbackStr("foo", @CallBack1() ,"stdcall")
So I changed @CallBack1 to @CallBack1() and get a different pointer than before.
Now the procedure gets called and the dialog is shown.
And the end of the procedure it throws an error:
[ERROR] Ungültiger Speicherzugriff. (Schreibfehler an der Adresse 0)
Translation: Invalid memory adress (write error at adress 0)
The row with EndProcedure is marked.
Still not sure how to correctly define the procedure param to get the Pchar UTF8 passed to the procedure.
And no idea why the that memory error is thrown at the end.
Regards
Re: callback procedure in Exe
Posted: Sun Oct 14, 2018 1:18 pm
by mk-soft
This works
But i don't known how to write newlisp scripts...
Code: Select all
;-TOP
; *******************************************************************
; -------------------------------------------------------------------
Prototype newLispEvalStrProto(EvalStr.p-utf8)
Prototype newlispCallbackStrProto(input.p-utf8, callbackaddress.i , calltype.p-utf8 )
Global _newLispEvalStr.newLispEvalStrProto
Global newlispCallbackStr.newlispCallbackStrProto
Global newlispLib
; -------------------------------------------------------------------
Procedure InitNewLisp()
newlispLib = OpenLibrary(#PB_Any,"newlisp.dll")
If newlispLib
_newLispEvalStr = GetFunction(newlispLib,"newlispEvalStr")
newlispCallbackStr = GetFunction(newlispLib, "newlispCallback")
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
; -------------------------------------------------------------------
Procedure.s newLispEvalStr(EvalStr.s)
Protected *result, result.s
*result = _newLispEvalStr(EvalStr)
If *result
result = PeekS(*result, -1, #PB_UTF8)
Else
result = "Error: No result"
EndIf
ProcedureReturn result
EndProcedure
; *******************************************************************
Global result.s, evalstr.s, r1
; -------------------------------------------------------------------
Procedure callme(*Info)
Protected text.s
If *Info
text = PeekS(*info, -1, #PB_UTF8)
ProcedureReturn MessageRequester("newLisp", "Result = " + text, #PB_MessageRequester_YesNoCancel)
Else
ProcedureReturn MessageRequester("newLisp", "No Info")
EndIf
EndProcedure
; -------------------------------------------------------------------
If InitNewLisp()
evalstr = "(callme 'Hello world')"
evalstr = ReplaceString(evalstr, "'", #DQUOTE$)
r1 = newlispCallbackStr("callme", @callme(), "stdcall")
If r1
result.s = newLispEvalStr(evalstr)
Debug "result = " + result
Else
Debug "Error: Register Callback"
EndIf
EndIf
Re: callback procedure in Exe
Posted: Sun Oct 14, 2018 1:40 pm
by mk-soft
How to return a string from callback
Code: Select all
;-TOP
; *******************************************************************
; -------------------------------------------------------------------
Prototype newLispEvalStrProto(EvalStr.p-utf8)
Prototype newlispCallbackStrProto(input.p-utf8, callbackaddress.i , calltype.p-utf8 )
Global _newLispEvalStr.newLispEvalStrProto
Global newlispCallbackStr.newlispCallbackStrProto
Global newlispLib
; -------------------------------------------------------------------
Procedure InitNewLisp()
newlispLib = OpenLibrary(#PB_Any,"newlisp.dll")
If newlispLib
_newLispEvalStr = GetFunction(newlispLib,"newlispEvalStr")
newlispCallbackStr = GetFunction(newlispLib, "newlispCallback")
ProcedureReturn #True
Else
ProcedureReturn #False
EndIf
EndProcedure
; -------------------------------------------------------------------
Procedure.s newLispEvalStr(EvalStr.s)
Protected *result, result.s
*result = _newLispEvalStr(EvalStr)
If *result
result = PeekS(*result, -1, #PB_UTF8)
Else
result = "Error: No result"
EndIf
ProcedureReturn result
EndProcedure
; *******************************************************************
Global result.s, evalstr.s, r1
; -------------------------------------------------------------------
Procedure callme(*Info)
Static *result
If *result
FreeMemory(*result)
EndIf
Protected text.s
If *Info
text = PeekS(*info, -1, #PB_UTF8)
text = ReverseString(text)
Else
text = "No Info!"
EndIf
*result = UTF8(text)
ProcedureReturn *result
EndProcedure
; -------------------------------------------------------------------
If InitNewLisp()
evalstr = ""
evalstr + "(get-string(callme 'Hello world'))"
evalstr = ReplaceString(evalstr, "'", #DQUOTE$)
r1 = newlispCallbackStr("callme", @callme(), "stdcall")
If r1
result.s = newLispEvalStr(evalstr)
Debug "result = " + result
Else
Debug "Error: Register Callback"
EndIf
EndIf
Re: callback procedure in Exe
Posted: Sun Oct 14, 2018 2:09 pm
by HPW
Hello,
Thanks to all advisers here and on the german forum.
I finally managed to get my newlisp demo to work with the callbacks.
Here is a complete purebasic source with the newlisp utf8 dll (32 bit):
http://www.hpwsoft.de/anmeldung/html1/n ... isp_PB.zip
Screenshot:
Edt: Forgot to mention that my Version contain a 32 bit Dll. I had developed on a 32 bit purebasic.
Other versions can be found here:
http://www.newlisp.org/downloads/development/
Regards
Hans-Peter
Re: callback procedure in Exe
Posted: Wed Oct 17, 2018 6:00 pm
by HPW
Hello,
Updated the demo with 2 more callbacks with Integer and Double parameters.
Again here is the complete purebasic source with the newlisp utf8 dll (32 bit):
This time also the compiled demo with 52224 Bytes.
http://www.hpwsoft.de/anmeldung/html1/n ... isp_PB.zip
Regards