Sciter学习:脚本与本地代码交互

Sciter学习:脚本与本地代码交互脚本呼叫本地方式一:Element.xcall需要实现event_handler_raw的on_script_call方法boolMainFrame::on_script_call(HELEMENThe,LPCSTRname,UINTargc,constSCITER_VALUE

大家好,欢迎来到IT知识分享网。Sciter学习:脚本与本地代码交互"

脚本呼叫本地

方式一:Element.xcall

需要实现event_handler_rawon_script_call方法

bool MainFrame::on_script_call(HELEMENT he, LPCSTR name, UINT argc, const SCITER_VALUE* argv, SCITER_VALUE& retval)
{
    // he:元素句柄,如果是窗口 Window.this 则为空
    // name:方法名称
    // argc:参数数量
    // argv:参数数组

    if (name == "test") {
        retval = 123; // 返回给脚本的值
    }
    return true; // 已处理
}

调用方法

console.log(Window.this.xcall('test', 1)); // 输出 "123"

https://github.com/c-smile/sciter-js-sdk/blob/main/docs/md/Element.md#elementxcallnamestring–arg0–argn-any

方式二:全局Asset

第一步,实现一个工具库类,需要继承自sciter::om::asset

#pragma once

#include <sciter-om.h>

class Util : public sciter::om::asset<Util>
{
public:
    Util() = default;

private:
    int test(sciter::value val) const
    {
        return val.get(0) + 10;
    }

    SOM_PASSPORT_BEGIN_EX(util, Util)  // 脚本中所使用的库名称
        SOM_FUNCS(
            SOM_FUNC(test) // 要暴露的方法
        )
    SOM_PASSPORT_END
};

第二步,向Sciter注册这个库
SciterSetGlobalAsset(new Util);
因为sciter::om::asset实现了引用计数,所以我们不用关心释放的问题。
第三步,使用

console.log(globalThis.util.test(5)); // 输出 15

前面的全局名称空间是可以省略掉的

console.log(util.test(5));

方式三:事件处理器中的Asset

由于我们的事件处理器一般继承自sciter::event_handler,而sciter::event_handler又继承了sciter::om::asset,所以我们也可以直接在事件处理器下定义要暴露的接口,这种情况下就不需要再通过SciterSetGlobalAsset去注册了。

class MainFrame :
	public sciter::host<MainFrame>,
	public sciter::event_handler
{
private:
    void test();

    SOM_PASSPORT_BEGIN_EX(frame, MainFrame)  // 和上面一样,定义脚本中的名称
        SOM_FUNCS(
            SOM_FUNC(test) // 暴露的方法
        )
    SOM_PASSPORT_END
};

在脚本中需要从窗口实例中调用,比如上面的代码这样调用:Window.this.frame.test()

本地呼叫脚本

C++调用JS函数只有一种方法:call_function,它是struct host的成员方法。由于我们的窗体都继承自host,所以可以直接用

this->call_function("foo", 1, L"hello");

表示调用JS中的全局函数foo,后面是参数,SDK重载了这个方法,最多支持携带4个参数

SCITER_VALUE  call_function( LPCSTR name )
{
    return(call_function( name, 0, 0 ) );
}

SCITER_VALUE  call_function( LPCSTR name, SCITER_VALUE arg0 )
{
    return(call_function( name, 1, &arg0 ) );
}

SCITER_VALUE  call_function( LPCSTR name, SCITER_VALUE arg0, SCITER_VALUE arg1 )
{
    SCITER_VALUE argv[2]; argv[0] = arg0; argv[1] = arg1;
    return(call_function( name, 2, argv ) );
}

SCITER_VALUE  call_function( LPCSTR name, SCITER_VALUE arg0, SCITER_VALUE arg1, SCITER_VALUE arg2 )
{
    SCITER_VALUE argv[3]; argv[0] = arg0; argv[1] = arg1; argv[2] = arg2;
    return(call_function( name, 3, argv ) );
}


SCITER_VALUE  call_function( LPCSTR name, SCITER_VALUE arg0, SCITER_VALUE arg1, SCITER_VALUE arg2, SCITER_VALUE arg3 )
{
    SCITER_VALUE argv[4]; argv[0] = arg0; argv[1] = arg1; argv[2] = arg2; argv[3] = arg3;
    return(call_function( name, 4, argv ) );
}

如果需要更多参数,可以这样用

SCITER_VALUE argv[8]; 
argv[0] = arg0;
...
argv[7] = arg7;
call_function( name, 8, argv);

方法要求在全局名称空间下

globalThis.foo = () => {};

建议不要省略前面的globalThs,因为在一个模块中定义方法,C++将无法调用,比如这样的情况

<script type="module"> // 这里表示是一个匿名模块
        function foo() {};  // 这个方法并不在全局名称空间中
</script>

正确写法应该是

<script type="module">
        globalThis.foo = () => {};
</script>

当定义大量函数时,可能会存在名称冲突的问题,因此可以将自己的函数定义到特定的名称空间下

class my 
{
  static test() {
    console.log('my.test');
  }
}

调用带名称空间的方法

call_function('my.test');

参考资料

Extended C++ interface support in Sciter

Native code exposure to script

include library “name” – native extensions

Sciter Object Model – extending Sciter by native code

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/32295.html

(0)

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信