ObjectScript API、C ++との統合。 パート4:C ++でカスタムクラスとカスタム関数を接続する

ObjectScriptは、新しいオープンソースのオブジェクト指向プログラミング言語です。 ObjectScriptは、JavaScript、Lua、PHPなどの言語の機能を拡張します。



以前の記事の結果に基づいて、C ++クラスと関数をObjectScriptに接続する方法について多くの質問がありました。 最初のOSビルドで利用できる接続方法はニーズをほとんど満たしていなかったため、より強力で便利なバインディングを作成することにしました。これは現在デフォルトOSに付属しています。



新しいバインディングの実際の利点は何ですか:ラッパーを追加せずに、任意の関数、任意のパラメーター、任意の戻り値を接続できるようになりました。 あなたが持っている機能をすぐに接続し、すべてが準備ができています。 また、OS上のスクリプトからC ++関数を呼び出すと、正しいパラメーターを受け取り、C ++から返される値がOS上のアナログに正しく変換されることを確認してください。



パート4:C ++でのカスタムクラスと関数のバインド



パート3では、低レベルの接続方法が説明されていましたが、保存されていました。 新しいメソッドは、関数を任意のパラメーター、任意の戻り値に接続する魔法を実装します。 さあ、行こう!



グローバル機能の接続



C ++に次の関数があるとします。



std::string getcwdString() { const int PATH_MAX = 1024; char buf[PATH_MAX]; getcwd(buf, PATH_MAX); return buf; }
      
      





OSのグローバルネームスペースに接続するには、コードを実行する必要があります。



 os->setGlobal(def("getcwd", getcwdString));
      
      





ObjectScriptから関数を呼び出します。



 print "getcwd: "..getcwd()
      
      





結論:



 getcwd: C:\Sources\OS\proj.win32\osbind
      
      





機能を備えたモジュールの接続



C ++に次の関数があるとします(これらの関数は完全に異なるデータ型を受け入れ、返すことに注意してください)。



 bool my_isdigit(const OS::String& str) { int len = str.getLen(); for(int i = 0; i < len; i++){ if(!isdigit(str[i])){ return false; } } return len > 0; } std::string my_hash(const char * str) { int i, len = strlen(str), hash = 5381; for(i = 0; i < len; i++){ hash = ((hash << 5) + hash) + str[i]; } hash &= 0x7fffffff; char buf[16]; for(i = 0; hash > 0; hash >>= 4){ buf[i++] = "0123456789abcdef"[hash & 0xf]; } buf[i] = 0; return buf; } void my_print_num(int i) { printf("my_print_num: %d\n", i); } void my_print_void(void) { printf("my_print_void\n"); } long double my_fabs(long double a) { return a >= 0 ? a : -a; }
      
      





もちろん、ユーザー定義関数は多くのパラメーターを取ることができます。 私のモジュールとしてOSに関数を接続します:



 OS::FuncDef funcs[] = { def("isdigit", my_isdigit), def("hash", my_hash), def("print_num", my_print_num), def("print_void", my_print_void), def("abs", my_fabs), {} }; os->getModule("my"); os->setFuncs(funcs); os->pop();
      
      





完了しました。OSで使用できるようになりました。



 print "isdigit(123): "..my.isdigit("123") print "isdigit(123q): "..my.isdigit("123q") print "my.hash(123): "..my.hash(123) print "call my.print_num(123.5)" my.print_num(123.5) print "call my.print_void()" my.print_void() print "my.abs(-12): "..my.abs(-12) print "my.fabs(-123.5): "..my.fabs(-123.5)
      
      





結論:



 isdigit(123): true isdigit(123q): false my.hash(123): bf9878b call my.print_num(123.5) my_print_num: 123 call my.print_void() my_print_void my.abs(-12): 12 my.fabs(-123.5): 123.5
      
      





C ++クラス接続



ここから楽しみが始まります。 OSコードで使用する次のC ++テストクラスがあるとします。



 class TestClass { public: int i; float j; TestClass(int _i, float _j){ i = _i; j = _j; } int getI() const { return i; } void setI(int _i){ i = _i; } float getJ() const { return j; } void setJ(float _j){ j = _j; } double doSomething(int a, float b, double c, TestClass * pb) { return i + j + a + b + c + pb->i + pb->j; } void print() { printf("test class: %d, %f\n", i, j); } };
      
      





OSに接続します。



 // 1.       ObjectScript // OS_DECL_USER_CLASS -  ,     //        C++ namespace ObjectScript { OS_DECL_USER_CLASS(TestClass); } // 2.   ,      TestClass * __constructTestClass(int i, float j){ return new TestClass(i, j); } // 3.        OS OS::FuncDef funcs[] = { def("__construct", __constructTestClass), def("__get@i", &TestClass::getI), def("__set@i", &TestClass::setI), def("__get@j", &TestClass::getJ), def("__set@j", &TestClass::setJ), def("doSomething", &TestClass::doSomething), def("print", &TestClass::print), {} }; registerUserClass<TestClass>(os, funcs);
      
      





完了、OSで確認:



 var t = TestClass(1, 0.25) print "ti: "..ti print "tj: "..tj var t2 = TestClass(2, 0.5) t2.i = t2.i + tj print "t2" t2.print() print "t.doSomething(10, 100.001, 1000.1, t2): "..t.doSomething(10, 100.001, 1000.1, t2)
      
      





結論:



 ti: 1 tj: 0.25 t2 test class: 2, 0.500000 t.doSomething(10, 100.001, 1000.1, t2): 1113.8509994506835
      
      





動作します! この記事のソースコードには、カスタムクラスのクローンを作成し、数学演算子をオーバーロードする方法も記載されています。



C ++でのカスタムデータ型の接続



まず、C ++でデータ構造があり、OSで値を持つコンテナとして検索する必要があるとします。



 struct TestStruct { float a, b; TestStruct(){ a = b = 0; } TestStruct(float _a, float _b){ a = _a; b = _b; } }; void printTestStruct(const TestStruct& p) { printf("TestStruct: %f %f\n", pa, pb); } TestStruct changeTestStruct(const TestStruct& p) { return TestStruct(pa*10, pb*100); }
      
      





OSに構造を操作するように教えましょう(パラメーターとして渡し、結果を返します)。



 namespace ObjectScript { OS_DECL_USER_CLASS(TestStruct); template <> struct CtypeValue<TestStruct> { // type   OS typedef TestStruct type; //  true,    C++      static bool isValid(const TestStruct&){ return true; } //       OS,   def static TestStruct def(ObjectScript::OS * os){ return TestStruct(0, 0); } //     OS static TestStruct getArg(ObjectScript::OS * os, int offs) { if(os->isObject(offs)){ os->getProperty(offs, "a"); // required float a = os->popFloat(); os->getProperty(offs, "b"); // required float b = os->popFloat(); return TestStruct(a, b); } os->triggerError(OS_E_ERROR, "TestStruct expected"); return TestStruct(0, 0); } //  OS      TestStruct static void push(ObjectScript::OS * os, const TestStruct& p) { os->newObject(); os->pushStackValue(); os->pushNumber(pa); os->setProperty("a"); os->pushStackValue(); os->pushNumber(pb); os->setProperty("b"); } }; } // namespace ObjectScript
      
      





グローバルOS名前空間でTestStructを操作するために、C ++で関数を登録します。



 os->setGlobal(def("printTestStruct", printTestStruct)); os->setGlobal(def("changeTestStruct", changeTestStruct));
      
      





OSをチェックインします。



 var data = {a=10 b=20} printTestStruct(data) data = changeTestStruct(data) printTestStruct(data) print data
      
      





結論:



 TestStruct: 10.000000 20.000000 TestStruct: 100.000000 2000.000000 {"a":100,"b":2000}
      
      





素晴らしい、すべてが機能します! すべての単純なデータ型(float、intなど)は、同じ方法でCtypeValueを介してOSで既に説明されています。 特定のデータ型変換OS-> C ++およびその逆を記述する必要がある場合は、CtypeValueを使用します。



この記事のObjectScriptのソースコードとサンプルをダウンロードするには、 このリンクにあるosbindプロジェクトのproj.win32 \ examples.slnを開きます。



ObjectScriptに関するその他の関連記事:






All Articles