ObjectScript API、C ++との統合。 パート3:モジュールとC ++の関数との接続

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

パート3:モジュールとC ++の関数との接続


OSコードで使用できる関数を含む独自のモジュールを作成しましょう。 モジュールをmyと呼びます。 2つの機能:


まず、C ++で将来のモジュールの関数を記述する必要があります。最初の関数はmy_isdigitです。

 static int my_isdigit(OS * os, int params, int, int, void*) { OS::String str = os->toString(-params); int len = str.getLen(); for(int i = 0; i < len; i++){ if(!isdigit(str[i])){ os->pushBool(false); return 1; } } os->pushBool(len > 0); return 1; } 

法案に関する簡単な説明:

 OS::String str = os->toString(-params); 

ここでは、最初のパラメーターを文字列として取得します。 paramsは、OSから関数に渡されたパラメーターの数です。 -paramsは、スタック上の最初のパラメーターへの相対ポインターです。 2番目のパラメーターを有効にする必要がある場合、 os->toString(-params+1)から3番目のos->toString(-params+2)などになります。

C ++ APIは、スタックからさまざまな単純型を取得するための多くの関数を提供します: toFloat, toDouble, toInt, toString, toUserdata, popFloatなど。

C ++プログラムでは、多くのスタック作業が発生する場合があります。 この場合、相対的なオフセットを念頭に置かないために(スタックに何かが追加または削除されると変更されるため)、スタック上の値への絶対ポインターを使用すると便利getAbsoluteOffs(int offs)関数で取得できますそして、このように動作します:

 int params_offs = os->getAbsoluteOffs(-params); OS::String str = os->toString(params_offs); //   OS::String str = os->toString(params_offs+1); //  

これは余談でしたが、モジュールの2番目の関数はmy_hashです:

 static int my_hash(OS * os, int params, int, int, void*) { OS::String str = os->toString(-params); int i, len = str.getLen(), 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; os->pushString(buf); return 1; } 

法案に関する簡単な説明:

  return 1; 

これは、関数によって返される値の数です。 関数の準備ができました。次の関数を持つ新しいモジュールがあることをOSに通知する必要があります。

 void initMyModule(OS * os) { OS::FuncDef funcs[] = { {"isdigit", my_isdigit}, {"hash", my_hash}, {} }; os->getModule("my"); os->setFuncs(funcs); os->pop(); } 

それがどのように動作するかを確認して、OS(main.os)でプログラムを書き、テスト配列の各値に対してC ++で関数を呼び出します:

 for(var i, s in ["123", "12w", 1234, " df", " "]){ print("my.isdigit("..s..") = "my.isdigit(s)" my.hash("..s..") = "my.hash(s)) } 

プログラムは次の結果を出力します。

 my.isdigit(123) = true my.hash(123) = bf9878b my.isdigit(12w) = false my.hash(12w) = f3a878b my.isdigit(1234) = true my.hash(1234) = f89c87c7 my.isdigit( df) = false my.hash( df) = f48478b my.isdigit( ) = false my.hash( ) = 5082f6c7 

C ++の完全なソースコード:

 #include "objectscript.h" #include <ctype.h> using namespace ObjectScript; static int my_isdigit(OS * os, int params, int, int, void*) { OS::String str = os->toString(-params); int len = str.getLen(); for(int i = 0; i < len; i++){ if(!isdigit(str[i])){ os->pushBool(false); return 1; } } os->pushBool(len > 0); return 1; } static int my_hash(OS * os, int params, int, int, void*) { OS::String str = os->toString(-params); int i, len = str.getLen(), hash = 5381; for(i = 0; i < len; i++){ hash = ((hash << 5) + hash) + str[i]; } char buf[16]; hash &= 0x7fffffff; for(i = 0; hash > 0; hash >>= 4){ buf[i++] = "0123456789abcdef"[hash & 0xf]; } buf[i] = 0; os->pushString(buf); return 1; } void initMyModule(OS * os) { OS::FuncDef funcs[] = { {"isdigit", my_isdigit}, {"hash", my_hash}, {} }; os->getModule("my"); os->setFuncs(funcs); os->pop(); } void main() { OS * os = OS::create(); initMyModule(os); os->require("main.os"); os->release(); } 


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

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


PS OS::Stringに関する小さな意見OS::String


OS :: Stringは、カスタムC ++コードに保存できるObjectScript文字列を持つオブジェクトです。 このような文字列は、存在する限り常に有効な値を保持します。 nullで終わる文字列を指すには、 toChar()関数を使用する必要があります。 ObjectScriptはメモリにすべての異なる行を1つのコピーで保存するため、 OS::Stringは一定の行であり、どのような状況でも変更できません。 ただし、新しい行を取得できます。 OS::Stringは多くのコンストラクターと連結演算子を実装しているため、 OS::Stringはユーザーコードから作成し、必要に応じて操作できます。

Q: OS::String前にos->release()実行されるとどうなりますかOS::Stringユーザーコードに保存されているOS::String列が破棄されますか?

A: OS :: StringはOSインスタンスをキャプチャし、外部コードで使用されていることを通知します。 したがって、 os->release()はOSインスタンスを破棄しませんが、最後のOS::Stringが存在しなくなると破棄されます。

Source: https://habr.com/ru/post/J153021/


All Articles