callback procedure in Exe

Just starting out? Need help? Post your questions and find answers here.
HPW
User
User
Posts: 26
Joined: Tue Apr 29, 2003 6:48 pm
Location: Germany

callback procedure in Exe

Post 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
Hans-Peter
Thorium
Addict
Addict
Posts: 1271
Joined: Sat Aug 15, 2009 6:59 pm

Re: callback procedure in Exe

Post 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()
HPW
User
User
Posts: 26
Joined: Tue Apr 29, 2003 6:48 pm
Location: Germany

Re: callback procedure in Exe

Post by HPW »

Hello,

Thanks for the tip. I will give it a try.

Regards
Hans-Peter
HPW
User
User
Posts: 26
Joined: Tue Apr 29, 2003 6:48 pm
Location: Germany

Re: callback procedure in Exe

Post 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
Hans-Peter
User avatar
spikey
Enthusiast
Enthusiast
Posts: 581
Joined: Wed Sep 22, 2010 1:17 pm
Location: United Kingdom

Re: callback procedure in Exe

Post 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
HPW
User
User
Posts: 26
Joined: Tue Apr 29, 2003 6:48 pm
Location: Germany

Re: callback procedure in Exe

Post 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
Hans-Peter
User avatar
spikey
Enthusiast
Enthusiast
Posts: 581
Joined: Wed Sep 22, 2010 1:17 pm
Location: United Kingdom

Re: callback procedure in Exe

Post by spikey »

My apologies - I meant to include this link but I managed to forget it... :oops:
viewtopic.php?f=12&t=52807

Like I said - I think this will work but I can't test to be certain.
HPW
User
User
Posts: 26
Joined: Tue Apr 29, 2003 6:48 pm
Location: Germany

Re: callback procedure in Exe

Post 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
Hans-Peter
HPW
User
User
Posts: 26
Joined: Tue Apr 29, 2003 6:48 pm
Location: Germany

Re: callback procedure in Exe

Post 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
Hans-Peter
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: callback procedure in Exe

Post by mk-soft »

This works :wink:

But i don't known how to write newlisp scripts... :mrgreen:

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 
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
User avatar
mk-soft
Always Here
Always Here
Posts: 5335
Joined: Fri May 12, 2006 6:51 pm
Location: Germany

Re: callback procedure in Exe

Post by mk-soft »

How to return a string from callback :wink:

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 
My Projects ThreadToGUI / OOP-BaseClass / EventDesigner V3
PB v3.30 / v5.75 - OS Mac Mini OSX 10.xx - VM Window Pro / Linux Ubuntu
Downloads on my Webspace / OneDrive
HPW
User
User
Posts: 26
Joined: Tue Apr 29, 2003 6:48 pm
Location: Germany

Re: callback procedure in Exe

Post 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:

Image

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
Hans-Peter
HPW
User
User
Posts: 26
Joined: Tue Apr 29, 2003 6:48 pm
Location: Germany

Re: callback procedure in Exe

Post 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
Hans-Peter
Post Reply