所以,我用所有静态方法创建了“接口类”,我希望将其暴露给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);
}
答案 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 );