パート3:モジュールとC ++の関数との接続
OSコードで使用できる関数を含む独自のモジュールを作成しましょう。 モジュールを
my
と呼びます。 2つの機能:
-
isdigit
は、パラメーターで渡された文字列が数字のみで構成されているかどうかを確認します -
hash
は、アルゴリズムに従ってパラメーターをハッシュ文字列に変換します
まず、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.slnのadd_user_moduleプロジェクトを開きます。
ObjectScriptに関するその他の関連記事:
- ObjectScript API、C ++との統合。 パート2:C ++からOS上でスクリプトを実行する
- ObjectScript API、C ++との統合。 パート1:スタックの操作、C ++からのOS関数の呼び出し
- 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
が存在しなくなると破棄されます。