Duktape JS

Just starting out? Need help? Post your questions and find answers here.
User avatar
the.weavster
Addict
Addict
Posts: 1577
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Duktape JS

Post 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.
infratec
Always Here
Always Here
Posts: 7625
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Duktape JS

Post 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)
User avatar
the.weavster
Addict
Addict
Posts: 1577
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Re: Duktape JS

Post 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.
infratec
Always Here
Always Here
Posts: 7625
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Duktape JS

Post 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.
User avatar
Caronte3D
Addict
Addict
Posts: 1362
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Duktape JS

Post by Caronte3D »

I don't understand what this Duktape JS is used for :?
Can you tell me some examples of use?
Thanks! :wink:
User avatar
the.weavster
Addict
Addict
Posts: 1577
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Re: Duktape JS

Post 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.
infratec
Always Here
Always Here
Posts: 7625
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Duktape JS

Post by infratec »

I would prefer lua if js is not needed.
User avatar
the.weavster
Addict
Addict
Posts: 1577
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Re: Duktape JS

Post 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.
infratec
Always Here
Always Here
Posts: 7625
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: Duktape JS

Post by infratec »

viewtopic.php?t=67365

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

But if this duktape fullfill your needs, why not?
User avatar
Dadido3
User
User
Posts: 54
Joined: Sat Jan 12, 2008 11:50 pm
Location: Hessen, Germany
Contact:

Re: Duktape JS

Post 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.
User avatar
the.weavster
Addict
Addict
Posts: 1577
Joined: Thu Jul 03, 2003 6:53 pm
Location: England

Re: Duktape JS

Post 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.
User avatar
Caronte3D
Addict
Addict
Posts: 1362
Joined: Fri Jan 22, 2016 5:33 pm
Location: Some Universe

Re: Duktape JS

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