Skip to content
kkk111 edited this page Jun 3, 2022 · 13 revisions

#Binder PSLにはC++の関数やクラスをスクリプトから容易に扱える様にする為のバインダがあります

##関数を登録する PSLVM p; p.addFunction("FunctionName", &func);

とすることで任意の関数funcをスクリプト側にFunctionNameの名前で登録することが出来ます.

引数や返り値はvariableで扱える型なら何でもよく、
引数の数は6つまでです.(それより多い関数を自動的に登録したい場合はbinder.hを拡張して下さい)

複数同時に登録する場合は

p.addFunction("func1", &func1)
	("func2", &func2)
	("func3", &func3);

と出来ます

##クラスを登録する class MyClass { public: MyClass(int i){member = i;} int getMember(){return member;} void setMember(int i){member = i;} private: int member; };

というクラスがあるとして

MyClass inst;
p.addClass<MyClass>("ClassName")
	("getMember", &MyClass::getMember)
	("setMember", &MyClass::setMember)
	.instance("instance", &inst);
// またはクラスの登録だけを先に行い
p.addInstance("Classname", "instance", &inst);
// とすることも出来ます

とするとスクリプト側にグローバル変数instanceが登録されます.
メソッドの引数の数は同じく6つまでです.

print(instance.getMember());
instance.setMember(10);

の様にアクセスする事が可能になります.
instanceはMyClass*型(ポインタ)としてバインドした関数やメソッドに渡すことも出来ます

またClassNameもスクリプトグローバル変数として登録されますが、
スクリプト側から直接これだけを扱うことは出来ません(自動的にnewする様なことはない)
newする関数も登録すれば扱う方法はあります.

##スクリプトからC++クラスのインスタンスを作成するには

class test
{
public:
	test(int i){x = i;}
	void set(int i){x = i;}
	int get()	{return x;}
	void destructor()	{delete this;}
	static test *New(int i)	{return new test(i);}
private:
	int x;
};
// ---
p.addClass<test>("test")
	("set", &test::set)
	("get", &test::get)
	("destructor", &test::destructor);
p.addFunction("new_test", &test::New);

// script
test t = new_test(5);
print(t.get());
t.set(10);
print(t.get());

スコープを抜ければnewしたインスタンスは自動的に解放されます.

更に

class
{
	return test t = new_test(0);
}

とでもしておけば

class c;
c.set(10);
print(c.get());

とか出来ます.

元のクラスに手を加えてNewやdestructorを用意することが難しい場合は

class test
{
public:
	test(int i){x = i;}
	void set(int i){x = i;}
	int get()	{return x;}
private:
	int x;
};
test *test_new(int i)	{return new test(i);}
PSL::variable test_deleter(PSL::variable &this_v, PSL::variable &v)
{
	test *p = this_v;
	delete p;
	return 0;
}
// ---
p.addClass<test>("test")
	("set", &test::set)
	("get", &test::get);
variable test_class = p.get("test");
test_class["destructor"] = variable(test_deleter);
p.addFunction("new_test", &test_new);

この様にします.
newの方は実質同じなので特に説明は要らないとして
destructorはvariable::method型の関数を用意して
受け取った(スクリプト上における)thisを元にdeleteします.

##グローバル変数として以外の方法でバインドする variable f(variable::Function(), &func);

variable classObject;
ClassObject["get"] = variable(variable::Method<test>(), &MyClass::getMember);
ClassObject["set"] = variable(variable::Method<test>(), &MyClass::setMember);

MyClass instance(5);
variable i = ClassObject.instance();
i[0] = &instance;

こうすることでバインダを使った場合と同じ内容のvariableをその場で作ることが出来ます
後はこのfなりiをPSLVM::run()の引数として渡すなり
スクリプトから受け取った関数に引数として渡すなり
出来ます

Clone this wiki locally