Page 1 of 1

Duktape JS

Posted: Sun Sep 05, 2021 9:05 pm
by the.weavster
I'm trying to get duktape to work with PB but I'm not getting very far. I can push a PB function on the stack and call it but I can't seem to expose it to JS :?

Windows binaries are here

This works:

Code: Select all

Enumeration
    #duk_dll
EndEnumeration

Define.i lResult = OpenLibrary(#duk_dll, "libduktape.dll")
If Not lResult
    MessageRequester("Error", "Failed to open library", 0)
    End
EndIf

Procedure.i show_text(*ctx)
    Define.i b
    b = CallCFunction(#duk_dll, "duk_get_string", *ctx, 0)
    Debug PeekS(b, -1, #PB_UTF8)
    ProcedureReturn 0
EndProcedure

*ctx = CallCFunction(#duk_dll, "duk_create_heap", #Null, #Null, #Null, #Null, #Null)
CallCFunction(#duk_dll, "duk_push_c_function", *ctx, @show_text(), 1)
CallCFunction(#duk_dll, "duk_push_string", *ctx, UTF8("Hello"))
CallCFunction(#duk_dll, "duk_call", *ctx, 1)
CallCFunction(#duk_dll, "duk_destroy_heap", *ctx)
But this doesn't:

Code: Select all

Enumeration
    #duk_dll
EndEnumeration

Define.i lResult = OpenLibrary(#duk_dll, "libduktape.dll")
If Not lResult
    MessageRequester("Error", "Failed to open library", 0)
    End
EndIf

Procedure.i show_text(*ctx)
    Define.i b
    b = CallCFunction(#duk_dll, "duk_get_string", *ctx, 0)
    Debug PeekS(b, -1, #PB_UTF8)
    ProcedureReturn 0
EndProcedure

*ctx = CallCFunction(#duk_dll, "duk_create_heap", #Null, #Null, #Null, #Null, #Null)
CallCFunction(#duk_dll, "duk_push_c_function", *ctx, @show_text(), 1)
CallCFunction(#duk_dll, "duk_put_global_string", *ctx, UTF8("foo"))
CallCFunction(#duk_dll, "duk_eval_string", *ctx, UTF8("foo('Hello');"))
CallCFunction(#duk_dll, "duk_destroy_heap", *ctx)
If anybody could point me in the right direction I'd be grateful.

Re: Duktape JS

Posted: Mon Sep 06, 2021 7:51 am
by infratec
Example 1:

Code: Select all

PrototypeC.i Prototype_duk_create_heap(*alloc_func, *realloc_func, *free_func, *heap_udata, *fatal_handler)
PrototypeC Prototype_duk_destroy_heap(*ctx)
PrototypeC.i Prototype_duk_get_string(*ctx, idx.i)
PrototypeC.i Prototype_duk_push_string(*ctx, str.p-utf8)
PrototypeC.i Prototype_duk_push_c_function(*ctx, *func, nargs.i)
PrototypeC Prototype_duk_call(*ctx, nargs.i)


Global duk_create_heap.Prototype_duk_create_heap
Global duk_destroy_heap.Prototype_duk_destroy_heap
Global duk_get_string_.Prototype_duk_get_string
Global duk_push_string.Prototype_duk_push_string
Global duk_push_c_function.Prototype_duk_push_c_function
Global duk_call.Prototype_duk_call


Procedure.s duk_get_string(*ctx, idx.i)
  
  Protected Result$, *String
  
  *String = duk_get_string_(*ctx, idx.i)
  If *String
    Result$ = PeekS(*String, -1, #PB_UTF8)
  EndIf
  
  ProcedureReturn Result$
  
EndProcedure



Define.i duk_library

duk_library = OpenLibrary(#PB_Any, "libduktape.dll")
If Not duk_library
    MessageRequester("Error", "Failed to open library", 0)
    End
EndIf

duk_create_heap = GetFunction(duk_library, "duk_create_heap")
duk_destroy_heap = GetFunction(duk_library, "duk_destroy_heap")
duk_get_string_ = GetFunction(duk_library, "duk_get_string")
duk_push_string = GetFunction(duk_library, "duk_push_string")
duk_push_c_function = GetFunction(duk_library, "duk_push_c_function")
duk_call = GetFunction(duk_library, "duk_call")




ProcedureC.i show_text(*ctx)    
    Debug duk_get_string(*ctx, 0)
    ProcedureReturn 0
EndProcedure

*ctx = duk_create_heap(#Null, #Null, #Null, #Null, #Null)
If *ctx
  duk_push_c_function(*ctx, @show_text(), 1)

  duk_push_string(*ctx, "Hello")
  duk_call(*ctx, 1)
  duk_destroy_heap(*ctx)
EndIf


Example 2:

Code: Select all

#DUK_COMPILE_EVAL = (1 << 3)
#DUK_COMPILE_NOSOURCE = (1 << 9)
#DUK_COMPILE_STRLEN = (1 << 10)
#DUK_COMPILE_NOFILENAME = (1 << 11)



PrototypeC.i Prototype_duk_create_heap(*alloc_func, *realloc_func, *free_func, *heap_udata, *fatal_handler)
PrototypeC Prototype_duk_destroy_heap(*ctx)
PrototypeC.i Prototype_duk_get_string(*ctx, idx.i)
PrototypeC.i Prototype_duk_push_string(*ctx, str.p-utf8)
PrototypeC.i Prototype_duk_push_c_function(*ctx, *func, nargs.i)
PrototypeC Prototype_duk_call(*ctx, nargs.i)
PrototypeC.i Prototype_duk_put_global_string(*ctx, key.p-utf8)
PrototypeC.i Prototype_duk_eval_raw(*ctx, *src_buffer, src_length.i, flags.i)


Global duk_create_heap.Prototype_duk_create_heap
Global duk_destroy_heap.Prototype_duk_destroy_heap
Global duk_get_string_.Prototype_duk_get_string
Global duk_push_string.Prototype_duk_push_string
Global duk_push_c_function.Prototype_duk_push_c_function
Global duk_call.Prototype_duk_call
Global duk_put_global_string.Prototype_duk_put_global_string
Global duk_eval_raw.Prototype_duk_eval_raw


Procedure duk_eval_string(*ctx, src.s)
  Protected *src
  
  *src = UTF8(src)
  duk_eval_raw(*ctx, *src, 0, 0 | #DUK_COMPILE_EVAL | #DUK_COMPILE_NOSOURCE | #DUK_COMPILE_STRLEN | #DUK_COMPILE_NOFILENAME)
  FreeMemory(*src)
  
EndProcedure




Procedure.s duk_get_string(*ctx, idx.i)
  
  Protected Result$, *String
  
  *String = duk_get_string_(*ctx, idx.i)
  If *String
    Result$ = PeekS(*String, -1, #PB_UTF8)
  EndIf
  
  ProcedureReturn Result$
  
EndProcedure



Define.i duk_library

duk_library = OpenLibrary(#PB_Any, "libduktape.dll")
If Not duk_library
    MessageRequester("Error", "Failed to open library", 0)
    End
EndIf

duk_create_heap = GetFunction(duk_library, "duk_create_heap")
duk_destroy_heap = GetFunction(duk_library, "duk_destroy_heap")
duk_get_string_ = GetFunction(duk_library, "duk_get_string")
duk_push_string = GetFunction(duk_library, "duk_push_string")
duk_push_c_function = GetFunction(duk_library, "duk_push_c_function")
duk_call = GetFunction(duk_library, "duk_call")
duk_put_global_string = GetFunction(duk_library, "duk_put_global_string")
duk_eval_raw = GetFunction(duk_library, "duk_eval_raw")


ProcedureC.i show_text(*ctx)    
    Debug duk_get_string(*ctx, 0)
    ProcedureReturn 0
EndProcedure


*ctx = duk_create_heap(#Null, #Null, #Null, #Null, #Null)
duk_push_c_function(*ctx, @show_text(), 1)
duk_put_global_string(*ctx, "foo")
duk_eval_string(*ctx, "foo('Hello');")
duk_destroy_heap(*ctx)

Re: Duktape JS

Posted: Mon Sep 06, 2021 8:10 am
by the.weavster
Thank you @infratec :D

I had just discovered not all the functions detailed in the API actually existed in the DLL but I still don't think I'd have figured it out without your help.

Re: Duktape JS

Posted: Mon Sep 06, 2021 8:16 am
by infratec
You should always use Prototypes.
Because then you can do things like

Code: Select all

duk_put_global_string(*ctx, "foo")
WIth p-utf8 the compiler does the necesarry conversion.

Re: Duktape JS

Posted: Mon Sep 06, 2021 9:00 am
by Caronte3D
I don't understand what this Duktape JS is used for :?
Can you tell me some examples of use?
Thanks! :wink:

Re: Duktape JS

Posted: Mon Sep 06, 2021 9:35 am
by the.weavster
Caronte3D wrote: Mon Sep 06, 2021 9:00 am I don't understand what this Duktape JS is used for :?
Can you tell me some examples of use?
Thanks! :wink:
In my case I have a web server I've coded in PB and I'd like to have some scripting capability built in.

Re: Duktape JS

Posted: Mon Sep 06, 2021 10:03 am
by infratec
I would prefer lua if js is not needed.

Re: Duktape JS

Posted: Mon Sep 06, 2021 10:55 am
by the.weavster
infratec wrote: Mon Sep 06, 2021 10:03 am I would prefer lua if js is not needed.
This is day 1 of my pondering so I'm still very persuadable :)

I'm only really looking at JS because of JSON rather than any fondness for the language. I was also influenced by the fact duktape just wants null terminated UTF8 strings which I thought would make passing data back and forth to PB easier. Is there a Lua library (preferably pure Lua) for converting a table to JSON?

If you have an example demonstrating opening a Lua script, exposing a PB function to Lua and passing the script's output back to PB I'd really appreciate it.

Re: Duktape JS

Posted: Mon Sep 06, 2021 11:41 am
by infratec
viewtopic.php?t=67365

https://github.com/Dadido3/Lua-PureBasic

But if this duktape fullfill your needs, why not?

Re: Duktape JS

Posted: Mon Sep 06, 2021 2:16 pm
by Dadido3
Regarding a JSON lib for lua. This one quite fast and small: https://github.com/rxi/json.lua

You just have to figure out how to get it to work with require. Lua has some rules where it searches for files that are "required", so either put that file into the same folder as the script you are calling it from, or put it in another folder and utilize

Code: Select all

package.path
to tell lua where to look for those files.

Re: Duktape JS

Posted: Mon Sep 06, 2021 4:02 pm
by the.weavster
Thanks @Dadido3

I've decided to stick with duktape, once @infratec's demo got me up and running I was very quickly able to implement a proof of concept that gives me the functionality I want to incorporate into my server.

Re: Duktape JS

Posted: Tue Sep 07, 2021 10:38 am
by Caronte3D
Would be nice if you share the source code of your server with DucktapeJS when you finish it
I'm curious about the use :wink: