Haxe / hscript - 防止将某些方法暴露给脚本

时间:2015-10-25 09:55:14

标签: haxe hxcpp

所以,我用所有静态方法创建了“接口类”,我希望将其暴露给hscript脚本。它看起来像这样:

package com.application.interfaces.Terrain;

import com.application.TerrainCore

class Terrain {

    private static var terrain:TerrainCore;

    public static function _init(inTerrain:TerrainCore):Void {
        terrain = inTerrain;
    }

    public static function test(s:Int):Void {
        terrain.test(s);
    }
}

问题是,我需要以某种方式设置terrain对象,但我不希望它暴露给脚本。我用

公开了整个班级
var interp = new Interp();
var module = Type.resolveClass("com.application.interfaces.Terrain");
interp.variables.set("Terrain", module)

我的想法是覆盖call中的方法hscript.Interp,因此它不会执行任何名为_init的方法,但我不知道该怎么做。原始call方法如下所示:

function call( o : Dynamic, f : Dynamic, args : Array<Dynamic> ) : Dynamic {
    return Reflect.callMethod(o,f,args);
}

2 个答案:

答案 0 :(得分:2)

您可以使用Terrain的类实例而不是使用静态成员吗​​?例如:

#include <stdio.h>
//#define N 101                                                                                                       
float foo(float *a, int n)
{
    float sum = 0;
    int i;
    #pragma omp parallel for simd reduction(+:sum)
    for(i=0; i<(n/8)*8; i++) sum += a[i];
    for(; i<n; i++) sum += a[i];
    return sum;
}

int main(void) {
    const int N = 101;
    float a[N]; for(int i=0; i<N; i++) a[i] = i;
    printf("%f\n", foo(a,N));
}

脚本用户不知道他们是否使用静态或实例方法,因为它仍然可以通过以下方式访问:

interp.variables.set("Terrain", new Terrain(new TerrainCore()));

在脚本中。

另一个选项(基于clemos)是使用rtti来计算出允许的内容(而不是维护它的列表),例如:

Terrain.test(123);

_init现在是一个私有函数,所以你需要从你的调用类Terrain._init(new TerrainCore()); 调用它(见下文),同样,你需要用@:allow进行注释,这样你就可以获取有关函数的信息。运行时,所以Terrain现在看起来像:

@:rtti

最后,脚本inter @:rtti class Terrain { private static var terrain:TerrainCore; @:allow(test.hscript.demo.Main) private static function _init(inTerrain:TerrainCore):Void { terrain = inTerrain; } public static function test(s:Int):Void { terrain.test(s); } } 现在表示字段是公共字段还是私有字段,即:

fcall

值得注意的是,由于显而易见的原因,我使用了public override function fcall(o:Dynamic, f:String, args:Array<Dynamic>):Dynamic var rtti = haxe.rtti.Rtti.getRtti(o); for (field in rtti.statics) { if (field.name == f && field.isPublic == false) { error(EInvalidAccess(f)); } } return super.fcall(o, f, args); } 而不是statics。我也不确定这会对循环和rtti造成什么开销。

答案 1 :(得分:2)

我认为你应该覆盖enum SimpleEnum : ExampleProtocol { case Desc(String) init() { self = Desc("a simple enum") } var simpleDescription:String { get { return (Mirror(reflecting: self).children.first!.value as? String)! } } mutating func adjust() { self = SimpleEnum.Desc(self.desc + " adjusted") } } var e = SimpleEnum() e.simpleDescription # => "a simple enum" e.adjust() e.simpleDescription # => "a simple enum adjusted" ,因为fcall仅用于顶级调用:

https://github.com/HaxeFoundation/hscript/blob/master/hscript/Interp.hx#L328-L331

过滤call参数应该很容易:

f

if ( FORBIDDEN_FIELDS.indexOf( f ) > -1 ) throw EInvalidAccess( f );