538 lines
49 KiB
HTML
538 lines
49 KiB
HTML
<?xml version="1.0" encoding="UTF-8"?>
|
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja">
|
|
<!-- generated by to_html.pl from simple.xml -->
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
|
<title>基本的な使い方</title>
|
|
<meta name="author" content="W.Dee" />
|
|
<meta http-equiv="Content-Style-Type" content="text/css" />
|
|
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
|
<link href="browser.css" type="text/css" rel="stylesheet" title="吉里吉里関連リファレンス用標準スタイル" />
|
|
<link href="mailto:[email protected]" rev="Made" />
|
|
<link href="index.html" target="_top" rel="Start" title="トップページ" />
|
|
</head>
|
|
<body>
|
|
<h1><a id="id318" name="id318">コンパイル</a>
|
|
</h1><div class="para"><div>
|
|
Borland C++ 5.5 以降 ( C++ Builder 5 以降 ) でコンパイルをすることができます。<br />
|
|
<br />
|
|
コンパイルには boost.org の regex++ が必要になります。<br />
|
|
<br />
|
|
regex++ をインストールした後、各 cpp ファイルをコンパイルしてください。<br />
|
|
<br />
|
|
C++ Builder の場合は、tjs2 の各 cpp ファイルをすべてプロジェクトに追加するだけで OK です。<br />
|
|
<br />
|
|
gcc 3 以降でもコンパイルできます ( 2.95 でもコンパイルできますが wstring 関連の修正が必要 )。<br />
|
|
</div></div>
|
|
<h1><a id="id319" name="id319">簡単な例</a>
|
|
</h1><div class="para"><div>
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /><span class="linenumber"> 1|</span>#include <stdio.h><br />
|
|
<span class="linenumber"> 2|</span>#include "tjs.h"<br />
|
|
<span class="linenumber"> 3|</span>#include "tjsError.h"<br />
|
|
<span class="linenumber"> 4|</span><br />
|
|
<span class="linenumber"> 5|</span>int main(int argc, char* argv[])<br />
|
|
<span class="linenumber"> 6|</span>{<br />
|
|
<span class="linenumber"> 7|</span> setlocale(LC_ALL, ""); <span class="comment">// ロケールを設定</span><br />
|
|
<span class="linenumber"> 8|</span><br />
|
|
<span class="linenumber"> 9|</span> tTJS *tjsengine = new tTJS(); <span class="comment">// TJS2 スクリプトエンジンを作成</span><br />
|
|
<span class="linenumber"> 10|</span><br />
|
|
<span class="linenumber"> 11|</span> try<br />
|
|
<span class="linenumber"> 12|</span> {<br />
|
|
<span class="linenumber"> 13|</span> tTJSVariant result; <span class="comment">// 結果を受け取るための変数</span><br />
|
|
<span class="linenumber"> 14|</span><br />
|
|
<span class="linenumber"> 15|</span> tjsengine->ExecScript(<br />
|
|
<span class="linenumber"> 16|</span> TJS_W(<br />
|
|
<span class="linenumber"> 17|</span> "function test(x, y) { return x*y; } \n"<br />
|
|
<span class="linenumber"> 18|</span> "return test(4, 5);\n"),<br />
|
|
<span class="linenumber"> 19|</span> &result, NULL,<br />
|
|
<span class="linenumber"> 20|</span> TJS_W("test code")); <span class="comment">// テストスクリプトを実行</span><br />
|
|
<span class="linenumber"> 21|</span><br />
|
|
<span class="linenumber"> 22|</span> printf("結果 : %d\n", (int)result); <span class="comment">// 結果を表示</span><br />
|
|
<span class="linenumber"> 23|</span> }<br />
|
|
<span class="linenumber"> 24|</span> catch(eTJSError &e)<br />
|
|
<span class="linenumber"> 25|</span> {<br />
|
|
<span class="linenumber"> 26|</span> printf("エラーが発生しました : %ls\n", e.GetMessage().c_str());<br />
|
|
<span class="linenumber"> 27|</span> }<br />
|
|
<span class="linenumber"> 28|</span> catch(...)<br />
|
|
<span class="linenumber"> 29|</span> {<br />
|
|
<span class="linenumber"> 30|</span> printf("エラーが発生しました\n");<br />
|
|
<span class="linenumber"> 31|</span> }<br />
|
|
<span class="linenumber"> 32|</span><br />
|
|
<span class="linenumber"> 33|</span> tjsengine->Shutdown(); <span class="comment">// TJS2 スクリプトエンジンをシャットダウン</span><br />
|
|
<span class="linenumber"> 34|</span> tjsengine->Release(); <span class="comment">// TJS2 スクリプトエンジンを解放</span><br />
|
|
<span class="linenumber"> 35|</span><br />
|
|
<span class="linenumber"> 36|</span> return 0;<br />
|
|
<span class="linenumber"> 37|</span>}<br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
<dl>
|
|
<dt>2~3行目</dt>
|
|
<dd>TJS2 を使用するのに必要なヘッダファイルを読み込んでいます。tjsError.h は TJS の C++ 例外に関する宣言が含まれています。</dd>
|
|
|
|
|
|
<dt>7行目</dt>
|
|
<dd>setlocale でロケールを指定しています。ロケールを指定しないと "C" ロケールになるため、日本語文字のナロー文字とワイド文字間の変換がうまくいきません。</dd>
|
|
|
|
|
|
<dt>9行目</dt>
|
|
<dd>TJS2 スクリプトエンジンを new 演算子で作成しています。</dd>
|
|
|
|
|
|
<dt>11行目</dt>
|
|
<dd>try ブロックに入っています。TJS2 のエラーは例外により通知されるため、例外処理には慎重になる必要があります。</dd>
|
|
|
|
|
|
<dt>13行目</dt>
|
|
<dd> スクリプトを実行した結果を受け取るための tTJSVariant 型の変数を宣言しています。</dd>
|
|
|
|
|
|
<dt>15~20行目</dt>
|
|
<dd> tTJS::ExecScript を使ってスクリプトを実行しています。<br />
|
|
第1引数には実行するスクリプトを指定します。tjs_char * 型で渡すために、文字列リテラルを TJS_W マクロを使ってワイド文字列に変換しています。スクリプトでは、関数 test を定義し、その関数を呼んだ結果を返しています。<br />
|
|
この例では return 文により実行の結果を返し、それを result 変数で受け取っていますが、結果を受け取る必要がない場合は return 文も tTJS::ExecScript の2番目の引数も必要ありません ( その場合は2番目の引数は NULL を指定します )。<br />
|
|
tTJS::ExecScript の3番目の引数は実行コンテキストですが、ここでは NULL を指定します。NULL を指定すると スクリプトは global コンテキスト上で実行されます。<br />
|
|
tTJS::ExecScript の4番目の引数は、このスクリプトの名前を指定します。NULLの場合は匿名として扱われます。人間が可読な名前である必要があります。</dd>
|
|
|
|
|
|
<dt>22行目</dt>
|
|
<dd> 結果を表示しています。ここでは tTJSVariant を int 型にキャストしています。</dd>
|
|
|
|
|
|
<dt>24行目</dt>
|
|
<dd> eTJSError 型の例外を受け取っています。</dd>
|
|
|
|
|
|
<dt>26行目</dt>
|
|
<dd> eTJSError::GetMessage を使って、例外の理由を表示しています。メッセージを const tjs_char * に変換するために tTJSString::c_str を使っています。tjs_char は ワイド文字のため、printf の変換指定子には %ls を指定しています。</dd>
|
|
|
|
|
|
<dt>28行目</dt>
|
|
<dd> その他の例外を受け取っています。</dd>
|
|
|
|
|
|
<dt>33~34行目</dt>
|
|
<dd> TJS2 スクリプトエンジンを解放しています。解放に先立ち、tTJS::Shutdown を使って TJS2 スクリプトエンジンをシャットダウンしています。</dd></dl></div></div>
|
|
|
|
<h1><a id="id320" name="id320">TJS2側の関数の呼び出し</a>
|
|
</h1><div class="para"><div>
|
|
TJS2側で宣言した関数をC++から呼び出す方法です。<br />
|
|
前述の try ブロックの中を以下のように書いてみます。<br />
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /><span class="linenumber"> 1|</span> tTJSVariant result; <span class="comment">// 結果を受け取るための変数</span><br />
|
|
<span class="linenumber"> 2|</span><br />
|
|
<span class="linenumber"> 3|</span> tjsengine->ExecScript(<br />
|
|
<span class="linenumber"> 4|</span> TJS_W("function test(x, y) { return x*y; }"), NULL, NULL, TJS_W("test"));<br />
|
|
<span class="linenumber"> 5|</span><br />
|
|
<span class="linenumber"> 6|</span> tjsengine->EvalExpression(TJS_W("test(4, 5)"), &result, NULL, NULL);<br />
|
|
<span class="linenumber"> 7|</span> <span class="comment">// tTJS::EvalExpression を使って式を実行</span><br />
|
|
<span class="linenumber"> 8|</span><br />
|
|
<span class="linenumber"> 9|</span> printf("結果 : %d\n", (int)result); <span class="comment">// 結果を表示</span><br />
|
|
<span class="linenumber"> 10|</span><br />
|
|
<span class="linenumber"> 11|</span> iTJSDispatch2 * global = tjsengine->GetGlobalNoAddRef();<br />
|
|
<span class="linenumber"> 12|</span> <span class="comment">// グローバルオブジェクトを取得</span><br />
|
|
<span class="linenumber"> 13|</span><br />
|
|
<span class="linenumber"> 14|</span> tTJSVariant param[] = { 4, 5 }; <span class="comment">// パラメータとして渡す変数</span><br />
|
|
<span class="linenumber"> 15|</span> tTJSVariant *p_param[] = { param + 0, param + 1 }; <span class="comment">// 変数へのポインタの配列</span><br />
|
|
<span class="linenumber"> 16|</span><br />
|
|
<span class="linenumber"> 17|</span> TJS_THROW_IF_ERROR(global->FuncCall(0, TJS_W("test"), NULL, &result, 2, p_param, NULL));<br />
|
|
<span class="linenumber"> 18|</span> <span class="comment">// test を関数として呼び出す</span><br />
|
|
<span class="linenumber"> 19|</span><br />
|
|
<span class="linenumber"> 20|</span> printf("結果 : %d\n", (int)result); <span class="comment">// 結果を表示</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
<dl>
|
|
<dt>3~4行目</dt>
|
|
<dd> 関数 test を宣言しています。test は global に登録されます。</dd>
|
|
|
|
|
|
<dt>6行目</dt>
|
|
<dd> tTJS::EvalExpression を使って式を実行しています。それほど速度的にシビアでなくてもよいならば、このように 式を文字列として渡してその結果を受け取ると楽です。<br />
|
|
ちなみに、単純な式 ( 関数宣言など、他の実行単位を含まないようなもの ) ならば、ある程度、コンパイル結果がキャッシュされ、2回目以降の式評価を高速に行うことができます。</dd>
|
|
|
|
|
|
<dt>11行目</dt>
|
|
<dd> グローバルオブジェクトを取得しています。tTJS::GetGlobal と tTJS::GetGlobalNoAddRef の違いは、前者が global オブジェクトの参照カウンタをインクリメントするのに対し、後者はインクリメントしないと言うことです。<br />
|
|
参照カウンタをインクリメントし、使い終わったらデクリメントすると言うことは、その間中、そのオブジェクトが消滅しないようにロックをかけると言うことです。この例のように、global オブジェクトが消滅する心配のない場合は参照カウンタを操作する必要はありませんので tTJS::GetGlobalNoAddRef を使うことができます。また、この場合は使い終わったときの Release は必要ありません。</dd>
|
|
|
|
|
|
<dt>14~15行目</dt>
|
|
<dd> 関数に渡すパラメータを準備しています。iTJSDispatch::FuncCall は、関数に渡すパラメータとして tTJSVariant 型のポインタの配列を必要とするため、このような準備が必要になります。</dd>
|
|
|
|
|
|
<dt>17行目</dt>
|
|
<dd> iTJSDispatch2::FuncCall を使って、関数 "test" を呼び出しています。<br />
|
|
FuncCall の最後の引数は、関数 test に渡される this (実行コンテキスト) ですが、この例で宣言した test 内では this を使っていないので NULL を指定してかまいません。実行すべきコンテキストがある場合は、そのオブジェクトを指定する必要があります。<br />
|
|
TJS_THROW_IF_ERROR は、tjs_error 型の結果がエラーだった場合、それに対応するエラーメッセージとともに例外を送出するマクロです。</dd></dl></div></div>
|
|
|
|
<h1><a id="id321" name="id321">ネイティブ関数</a>
|
|
</h1><div class="para"><div>
|
|
ネイティブ実装 (C++などで実装された関数) を作成し、TJS2 側からそれにアクセスすることができます。<br />
|
|
C++ でなくても、iTJSDispatch2 を実装できる言語ならば、どのような言語で書かれた関数でも呼び出すことができますが、C++ が一番楽でしょう。<br />
|
|
<br />
|
|
C++ で 関数を書く場合は、tTJSNativeFunction (tjsNative.h に記述) からクラスを導出するのが楽です (しかし、iTJSDispatch2 の FuncCall を実装するだけでも関数として動作はできます)。<br />
|
|
<br />
|
|
与えられた2つの引数を乗算して返す、簡単な関数を実装してみます。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /><span class="linenumber"> 1|</span>class TestFunc : public tTJSNativeFunction<br />
|
|
<span class="linenumber"> 2|</span>{<br />
|
|
<span class="linenumber"> 3|</span>public:<br />
|
|
<span class="linenumber"> 4|</span> tjs_error Process(tTJSVariant *result, tjs_int numparams,<br />
|
|
<span class="linenumber"> 5|</span> tTJSVariant **param, iTJSDispatch2 *objthis)<br />
|
|
<span class="linenumber"> 6|</span> {<br />
|
|
<span class="linenumber"> 7|</span> if(numparams < 2) return TJS_E_BADPARAMCOUNT; <span class="comment">// 引数が足りない</span><br />
|
|
<span class="linenumber"> 8|</span><br />
|
|
<span class="linenumber"> 9|</span> if(!result) return TJS_S_OK; <span class="comment">// 結果を格納しなくて良い場合はそのままもどる</span><br />
|
|
<span class="linenumber"> 10|</span><br />
|
|
<span class="linenumber"> 11|</span> *result = *param[0] * *param[1]; <span class="comment">// 計算</span><br />
|
|
<span class="linenumber"> 12|</span><br />
|
|
<span class="linenumber"> 13|</span> return TJS_S_OK; <span class="comment">// 正常に終わったことを示すため TJS_S_OK を返す</span><br />
|
|
<span class="linenumber"> 14|</span> }<br />
|
|
<span class="linenumber"> 15|</span>};<br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
tTJSNativeFunction を継承したクラスで実装すべきなのは、上記の通り Process メソッドだけです。<br />
|
|
Process メソッドの引数は以下の通りです。<br />
|
|
<br />
|
|
<dl>
|
|
<dt>tTJSVariant *result</dt>
|
|
<dd> 関数の結果を格納するための tTJSVariant 型の変数へのポインタが渡されます。<em>呼び出し側が結果を必要としない場合は NULL が渡されます</em>ので注意してください。</dd>
|
|
|
|
|
|
<dt>tjs_int numparams</dt>
|
|
<dd> 関数に渡された引数の数です。</dd>
|
|
|
|
|
|
<dt>tTJSVariant **param</dt>
|
|
<dd> 関数に渡された引数が格納された tTJSVariant 型の変数へのポインタの配列です。</dd>
|
|
|
|
|
|
<dt>iTJSDispatch2 *objthis</dt>
|
|
<dd> 関数が実行されるべきコンテキストです。コンテキストに依存しない実装をする場合は無視してかまいません。</dd></dl><br />
|
|
<br />
|
|
<br />
|
|
ネイティブ関数は TJS2 からアクセス可能にするため、TJS2 内からアクセスできるオブジェクトに登録する必要があります。以下の例では、global に "test" という名前で登録しています。また、実際にその関数を呼び出しています。<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /><span class="linenumber"> 1|</span> iTJSDispatch2 * global = tjsengine->GetGlobalNoAddRef();<br />
|
|
<span class="linenumber"> 2|</span> <span class="comment">// グローバルオブジェクトを取得</span><br />
|
|
<span class="linenumber"> 3|</span><br />
|
|
<span class="linenumber"> 4|</span> iTJSDispatch2 *func = new TestFunc(); <span class="comment">// TestFunc のオブジェクトを作成</span><br />
|
|
<span class="linenumber"> 5|</span> tTJSVariant func_var(func); <span class="comment">// tTJSVariant 型 func_var にオブジェクトを設定</span><br />
|
|
<span class="linenumber"> 6|</span> func->Release(); <span class="comment">// func を Release</span><br />
|
|
<span class="linenumber"> 7|</span><br />
|
|
<span class="linenumber"> 8|</span> TJS_THROW_IF_ERROR(<br />
|
|
<span class="linenumber"> 9|</span> global->PropSet(TJS_MEMBERENSURE, TJS_W("test"), NULL, &func_var, NULL));<br />
|
|
<span class="linenumber"> 10|</span> <span class="comment">// 登録</span><br />
|
|
<span class="linenumber"> 11|</span><br />
|
|
<span class="linenumber"> 12|</span> tTJSVariant result; <span class="comment">// 結果を受け取るための変数</span><br />
|
|
<span class="linenumber"> 13|</span> tjsengine->EvalExpression(TJS_W("test(4, 5)"), &result, NULL, NULL);<br />
|
|
<span class="linenumber"> 14|</span> <span class="comment">// tTJS::EvalExpression を使って式を実行</span><br />
|
|
<span class="linenumber"> 15|</span><br />
|
|
<span class="linenumber"> 16|</span> printf("結果 : %d\n", (int)result); <span class="comment">// 結果を表示</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
<dl>
|
|
<dt>4~6行目</dt>
|
|
<dd> ネイティブ関数を実装してあるクラス TestFunc のオブジェクトを作成し、それを tTJSVariant 型に変換しています。<br />
|
|
5行目で tTJSVariant 型に変換していますが、この時点で tTJSVariant 型が 関数オブジェクトの参照カウンタを自動的に管理するので、6行目で関数オブジェクトを Release しています。</dd>
|
|
|
|
|
|
<dt>8~9行目</dt>
|
|
<dd> global オブジェクトに関数を "test" という名前で登録しています。global オブジェクトの iTJSDispatch2::PropSet を呼んでいますが、メンバを新規作成させるために TJS_MEMBERENSURE フラグを伴って呼び出しています。</dd>
|
|
|
|
|
|
<dt>12~16行目</dt>
|
|
<dd> 実際に関数を呼び出し、結果を表示しています。</dd></dl></div></div>
|
|
<h1><a id="id322" name="id322">ネイティブクラス</a>
|
|
</h1><div class="para"><div>
|
|
TJS2 は C++ 等の言語で書かれたネイティブクラスを扱うための機構を持っています。<br />
|
|
各オブジェクト (iTJSDispatch2 インターフェース) にはネイティブインスタンスと呼ばれる、iTJSNativeInstance 型のオブジェクトを登録することができ、これを オブジェクトから取り出すことができます。<br />
|
|
ネイティブインスタンスは一意なクラス ID で識別され、ネイティブクラスの作成時にはクラス ID を取得する必要があります。<br />
|
|
<br />
|
|
しかし、これらの操作を行う為のマクロ群が tjsNative.h に定義されているので、これらを利用するのが楽です。<br />
|
|
以下の例は、これらのマクロを使って簡単なクラスを実装するものです。<br />
|
|
<br />
|
|
まず、ネイティブインスタンスの実装です。ネイティブインスタンスを実装するには tTJSNativeInstance からクラスを導出します。tTJSNativeInstance は tjsNative.cpp / tjsNative.h に実装されているクラスで、iTJSNativeInstance の基本的な動作を実装しています。<br />
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /><span class="linenumber"> 1|</span>class NI_Test : public tTJSNativeInstance <span class="comment">// ネイティブインスタンス</span><br />
|
|
<span class="linenumber"> 2|</span>{<br />
|
|
<span class="linenumber"> 3|</span>public:<br />
|
|
<span class="linenumber"> 4|</span> NI_Test()<br />
|
|
<span class="linenumber"> 5|</span> {<br />
|
|
<span class="linenumber"> 6|</span> <span class="comment">// コンストラクタ</span><br />
|
|
<span class="linenumber"> 7|</span> Value = 0;<br />
|
|
<span class="linenumber"> 8|</span> }<br />
|
|
<span class="linenumber"> 9|</span><br />
|
|
<span class="linenumber"> 10|</span> tjs_error TJS_INTF_METHOD<br />
|
|
<span class="linenumber"> 11|</span> Construct(tjs_int numparams, tTJSVariant **param, iTJSDispatch2 *tjs_obj)<br />
|
|
<span class="linenumber"> 12|</span> {<br />
|
|
<span class="linenumber"> 13|</span> <span class="comment">// TJS2 オブジェクトが作成されるときに呼ばれる</span><br />
|
|
<span class="linenumber"> 14|</span><br />
|
|
<span class="linenumber"> 15|</span> <span class="comment">// 引数があればそれを初期値として Value に入れる</span><br />
|
|
<span class="linenumber"> 16|</span> if(numparams >= 1 && param[0]->Type() != tvtVoid)<br />
|
|
<span class="linenumber"> 17|</span> Value = (tjs_int)*param[0];<br />
|
|
<span class="linenumber"> 18|</span><br />
|
|
<span class="linenumber"> 19|</span> return S_OK;<br />
|
|
<span class="linenumber"> 20|</span> }<br />
|
|
<span class="linenumber"> 21|</span><br />
|
|
<span class="linenumber"> 22|</span> void TJS_INTF_METHOD Invalidate()<br />
|
|
<span class="linenumber"> 23|</span> {<br />
|
|
<span class="linenumber"> 24|</span> <span class="comment">// オブジェクトが無効化されるときに呼ばれる</span><br />
|
|
<span class="linenumber"> 25|</span> }<br />
|
|
<span class="linenumber"> 26|</span><br />
|
|
<span class="linenumber"> 27|</span> void SetValue(tjs_int n) { Value = n; }<br />
|
|
<span class="linenumber"> 28|</span> tjs_int GetValue() const { return Value; }<br />
|
|
<span class="linenumber"> 29|</span><br />
|
|
<span class="linenumber"> 30|</span> tjs_int GetSquare() const { return Value*Value; }<br />
|
|
<span class="linenumber"> 31|</span> void Add(tjs_int n) { Value += n; }<br />
|
|
<span class="linenumber"> 32|</span> void Print() const { printf("%d\n", Value); }<br />
|
|
<span class="linenumber"> 33|</span><br />
|
|
<span class="linenumber"> 34|</span>private:<br />
|
|
<span class="linenumber"> 35|</span> tjs_int Value; <span class="comment">// 値</span><br />
|
|
<span class="linenumber"> 36|</span>};<br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
<dl>
|
|
<dt>35行目</dt>
|
|
<dd> 話が前後しますが、データメンバです。ネイティブインスタンスには、必要なデータメンバを自由に書くことができます。</dd>
|
|
|
|
<dt>4~8行目</dt>
|
|
<dd> NI_Test のコンストラクタです。C++ クラスとしての初期化は 後述の Construct よりもここで済ませておき、Construct での初期化は最小限の物にすることをおすすめします。<br />
|
|
この例では、データメンバの Value に初期値として 0 を設定しています。</dd>
|
|
|
|
|
|
<dt>10~20行目</dt>
|
|
<dd> new 演算子で TJS2 オブジェクトが作成されるときに呼ばれます。numparams と param 引数は new 演算子に渡された引数を表しています。<br />
|
|
tjs_obj 引数は、作成される TJS オブジェクトです。<br />
|
|
この例では、引数があれば (さらにそれが void で無ければ )、それを Value の初期値として設定しています。</dd>
|
|
|
|
|
|
<dt>22~25行目</dt>
|
|
<dd> オブジェクトが無効化されるときに呼ばれるメソッドです。ここに終了処理を書くと良いでしょう。<br />
|
|
この例では何もしません。</dd>
|
|
|
|
|
|
<dt>27~32行目</dt>
|
|
<dd> データメンバを操作するための公開メソッド群です。後述するネイティブクラス内で、これらを利用するコードを書きます。</dd></dl><br />
|
|
オブジェクトを作成するためにはクラスが必要ですので、クラスを記述します。クラスは tTJSNativeClass を導出する形で実装します。tTJSNativeClass は iTJSDispatch2 インターフェースを持っていて、ネイティブクラスとして振る舞うための基本的な動作が実装されています。<br />
|
|
TJS からアクセス可能なメソッドやプロパティは、ネイティブクラスのコンストラクタ内に記述します。<br />
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /><span class="linenumber"> 1|</span>class NC_Test : public tTJSNativeClass <span class="comment">// ネイティブクラス</span><br />
|
|
<span class="linenumber"> 2|</span>{<br />
|
|
<span class="linenumber"> 3|</span>public:<br />
|
|
<span class="linenumber"> 4|</span> NC_Test(); <span class="comment">// コンストラクタ; 下に記述</span><br />
|
|
<span class="linenumber"> 5|</span><br />
|
|
<span class="linenumber"> 6|</span> static tjs_uint32 ClassID; <span class="comment">// クラスID</span><br />
|
|
<span class="linenumber"> 7|</span><br />
|
|
<span class="linenumber"> 8|</span>private:<br />
|
|
<span class="linenumber"> 9|</span> tTJSNativeInstance *CreateNativeInstance()<br />
|
|
<span class="linenumber"> 10|</span> {<br />
|
|
<span class="linenumber"> 11|</span> return new NI_Test(); <span class="comment">// ネイティブインスタンスを作成して返す</span><br />
|
|
<span class="linenumber"> 12|</span> }<br />
|
|
<span class="linenumber"> 13|</span>};<br />
|
|
<span class="linenumber"> 14|</span>tjs_uint32 NC_Test::ClassID = (tjs_uint32)-1; <span class="comment">// クラスID</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
<dl>
|
|
<dt>4行目</dt>
|
|
<dd> このクラスのコンストラクタです。実装は後述します。</dd>
|
|
|
|
|
|
<dt>6行目</dt>
|
|
<dd> このクラスのクラス ID を保持するための変数です。14行目に実体があります。</dd>
|
|
|
|
|
|
<dt>9~12行目</dt>
|
|
<dd> CreateNativeInstance メソッドは、ネイティブインスタンスを作成すべきタイミングで呼ばれるメソッドです。ここでは NI_Test クラスのオブジェクトを作成して返しています。</dd></dl><br />
|
|
<br />
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /><span class="linenumber"> 1|</span>NC_Test::NC_Test() : tTJSNativeClass(TJS_W("Test"))<br />
|
|
<span class="linenumber"> 2|</span>{<br />
|
|
<span class="linenumber"> 3|</span> TJS_BEGIN_NATIVE_MEMBERS(<span class="comment">/*TJS class name*/</span>Test)<br />
|
|
<span class="linenumber"> 4|</span><br />
|
|
<span class="linenumber"> 5|</span> TJS_DECL_EMPTY_FINALIZE_METHOD<br />
|
|
<span class="linenumber"> 6|</span><br />
|
|
<span class="linenumber"> 7|</span> TJS_BEGIN_NATIVE_CONSTRUCTOR_DECL(<br />
|
|
<span class="linenumber"> 8|</span> <span class="comment">/*var.name*/</span>_this,<br />
|
|
<span class="linenumber"> 9|</span> <span class="comment">/*var.type*/</span>NI_Test,<br />
|
|
<span class="linenumber"> 10|</span> <span class="comment">/*TJS class name*/</span>Test)<br />
|
|
<span class="linenumber"> 11|</span> {<br />
|
|
<span class="linenumber"> 12|</span> <span class="comment">// NI_Test::Construct にも内容を記述できるので</span><br />
|
|
<span class="linenumber"> 13|</span> <span class="comment">// ここでは何もしない</span><br />
|
|
<span class="linenumber"> 14|</span> return TJS_S_OK;<br />
|
|
<span class="linenumber"> 15|</span> }<br />
|
|
<span class="linenumber"> 16|</span> TJS_END_NATIVE_CONSTRUCTOR_DECL(<span class="comment">/*TJS class name*/</span>Test)<br />
|
|
<span class="linenumber"> 17|</span><br />
|
|
<span class="linenumber"> 18|</span> TJS_BEGIN_NATIVE_METHOD_DECL(<span class="comment">/*func. name*/</span>print) <span class="comment">// print メソッド</span><br />
|
|
<span class="linenumber"> 19|</span> {<br />
|
|
<span class="linenumber"> 20|</span> TJS_GET_NATIVE_INSTANCE(<span class="comment">/*var. name*/</span>_this,<br />
|
|
<span class="linenumber"> 21|</span> <span class="comment">/*var. type*/</span>NI_Test);<br />
|
|
<span class="linenumber"> 22|</span><br />
|
|
<span class="linenumber"> 23|</span> _this->Print();<br />
|
|
<span class="linenumber"> 24|</span><br />
|
|
<span class="linenumber"> 25|</span> return TJS_S_OK;<br />
|
|
<span class="linenumber"> 26|</span> }<br />
|
|
<span class="linenumber"> 27|</span> TJS_END_NATIVE_METHOD_DECL(<span class="comment">/*func. name*/</span>print)<br />
|
|
<span class="linenumber"> 28|</span><br />
|
|
<span class="linenumber"> 29|</span> TJS_BEGIN_NATIVE_METHOD_DECL(<span class="comment">/*func. name*/</span>add) <span class="comment">// add メソッド</span><br />
|
|
<span class="linenumber"> 30|</span> {<br />
|
|
<span class="linenumber"> 31|</span> TJS_GET_NATIVE_INSTANCE(<span class="comment">/*var. name*/</span>_this,<br />
|
|
<span class="linenumber"> 32|</span> <span class="comment">/*var. type*/</span>NI_Test);<br />
|
|
<span class="linenumber"> 33|</span><br />
|
|
<span class="linenumber"> 34|</span> if(numparams < 1) return TJS_E_BADPARAMCOUNT;<br />
|
|
<span class="linenumber"> 35|</span><br />
|
|
<span class="linenumber"> 36|</span> _this->Add((tjs_int)*param[0]);<br />
|
|
<span class="linenumber"> 37|</span><br />
|
|
<span class="linenumber"> 38|</span> return TJS_S_OK;<br />
|
|
<span class="linenumber"> 39|</span> }<br />
|
|
<span class="linenumber"> 40|</span> TJS_END_NATIVE_METHOD_DECL(<span class="comment">/*func. name*/</span>add)<br />
|
|
<span class="linenumber"> 41|</span><br />
|
|
<span class="linenumber"> 42|</span> TJS_BEGIN_NATIVE_PROP_DECL(value) <span class="comment">// value プロパティ</span><br />
|
|
<span class="linenumber"> 43|</span> {<br />
|
|
<span class="linenumber"> 44|</span> TJS_BEGIN_NATIVE_PROP_GETTER<br />
|
|
<span class="linenumber"> 45|</span> {<br />
|
|
<span class="linenumber"> 46|</span> TJS_GET_NATIVE_INSTANCE(<span class="comment">/*var. name*/</span>_this,<br />
|
|
<span class="linenumber"> 47|</span> <span class="comment">/*var. type*/</span>NI_Test);<br />
|
|
<span class="linenumber"> 48|</span> *result = _this->GetValue();<br />
|
|
<span class="linenumber"> 49|</span> return TJS_S_OK;<br />
|
|
<span class="linenumber"> 50|</span> }<br />
|
|
<span class="linenumber"> 51|</span> TJS_END_NATIVE_PROP_GETTER<br />
|
|
<span class="linenumber"> 52|</span><br />
|
|
<span class="linenumber"> 53|</span> TJS_BEGIN_NATIVE_PROP_SETTER<br />
|
|
<span class="linenumber"> 54|</span> {<br />
|
|
<span class="linenumber"> 55|</span> TJS_GET_NATIVE_INSTANCE(<span class="comment">/*var. name*/</span>_this,<br />
|
|
<span class="linenumber"> 56|</span> <span class="comment">/*var. type*/</span>NI_Test);<br />
|
|
<span class="linenumber"> 57|</span> _this->SetValue((tjs_int)*param);<br />
|
|
<span class="linenumber"> 58|</span> return TJS_S_OK;<br />
|
|
<span class="linenumber"> 59|</span> }<br />
|
|
<span class="linenumber"> 60|</span> TJS_END_NATIVE_PROP_SETTER<br />
|
|
<span class="linenumber"> 61|</span> }<br />
|
|
<span class="linenumber"> 62|</span> TJS_END_NATIVE_PROP_DECL(value)<br />
|
|
<span class="linenumber"> 63|</span><br />
|
|
<span class="linenumber"> 64|</span> TJS_BEGIN_NATIVE_PROP_DECL(square) <span class="comment">// square 読み出し専用プロパティ</span><br />
|
|
<span class="linenumber"> 65|</span> {<br />
|
|
<span class="linenumber"> 66|</span> TJS_BEGIN_NATIVE_PROP_GETTER<br />
|
|
<span class="linenumber"> 67|</span> {<br />
|
|
<span class="linenumber"> 68|</span> TJS_GET_NATIVE_INSTANCE(<span class="comment">/*var. name*/</span>_this,<br />
|
|
<span class="linenumber"> 69|</span> <span class="comment">/*var. type*/</span>NI_Test);<br />
|
|
<span class="linenumber"> 70|</span><br />
|
|
<span class="linenumber"> 71|</span> *result = _this->GetSquare();<br />
|
|
<span class="linenumber"> 72|</span><br />
|
|
<span class="linenumber"> 73|</span> return TJS_S_OK;<br />
|
|
<span class="linenumber"> 74|</span> }<br />
|
|
<span class="linenumber"> 75|</span> TJS_END_NATIVE_PROP_GETTER<br />
|
|
<span class="linenumber"> 76|</span><br />
|
|
<span class="linenumber"> 77|</span> TJS_DENY_NATIVE_PROP_SETTER<br />
|
|
<span class="linenumber"> 78|</span> }<br />
|
|
<span class="linenumber"> 79|</span> TJS_END_NATIVE_PROP_DECL(square)<br />
|
|
<span class="linenumber"> 80|</span><br />
|
|
<span class="linenumber"> 81|</span> TJS_END_NATIVE_MEMBERS<br />
|
|
<span class="linenumber"> 82|</span>}<br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
<dl>
|
|
<dt>1行目</dt>
|
|
<dd> NC_Test のコンストラクタです。親クラスである tTJSNativeClass のコンストラクタには TJS2 内で使用するクラス名を指定します。</dd>
|
|
|
|
|
|
<dt>3行目</dt>
|
|
<dd> TJS_BEGIN_NATIVE_MEMBERS マクロです。引数には TJS2 内で使用するクラス名を指定します。<br />
|
|
このマクロと TJS_END_NATIVE_MEMBERS マクロで挟まれた場所に、クラスのメンバとなるべきメソッドやプロパティの記述をします。</dd>
|
|
|
|
|
|
<dt>4行目</dt>
|
|
<dd> 空の finalize メソッドを宣言しています。finalize に相当する処理は tTJSNativeInstance::Invalidate をオーバーライドすることでも実装できますので、通常は空のメソッドで十分です。
|
|
</dd>
|
|
|
|
|
|
<dt>7~16行目</dt>
|
|
<dd> (TJSの) コンストラクタを宣言しています。TJS でクラスを書くとき、クラス内でクラスと同名のメソッドを宣言している部分に相当します。<br />
|
|
<br />
|
|
TJS_BEGIN_NATIVE_CONSTRUCTOR_DECL マクロの1番目の引数はネイティブインスタンスに割り当てる変数名で、2場面目の引数はその変数の型名です。この例でのこのブロック内では NI_Test * _this という変数が利用可能で、ネイティブインスタンスにアクセスすることができます。<br />
|
|
マクロの3番目の引数は、TJS 内で使用するクラス名を指定します。TJS_END_NATIVE_CONSTRUCTOR_DECL マクロの引数も同様です。<br />
|
|
ここも、コンストラクタに相当する処理は tTJSNativeInstance::Construct をオーバーライドする事で実装できるので、ここでは何もせずに S_OK を返します。
|
|
</dd>
|
|
|
|
|
|
<dt>18~27行目</dt>
|
|
<dd> print メソッドを宣言しています。メソッド名は TJS_BEGIN_NATIVE_METHOD_DECL と TJS_END_NATIVE_METHOD_DECL の両マクロに同じものを指定する必要があります。<br />
|
|
このマクロ内で使用可能な変数に tjs_int numparams と tTJSVariant **param があって、それぞれ、渡された引数の数と引数を示しています。このメソッドではそれらは使用していません。<br />
|
|
20~21行目は、オブジェクトからネイティブインスタンスを取り出すためのマクロです。この例では _this という NI_Test * 型の変数にネイティブインスタンスを取り出す、という意味になります。以降、_this という変数でネイティブインスタンスにアクセスできます。23行目で、そのネイティブインスタンスの Print メソッドを呼び出しています。</dd>
|
|
|
|
|
|
<dt>29~40行目</dt>
|
|
<dd> add メソッドを宣言しています。ここでは numparams と param を使用しています。</dd>
|
|
|
|
|
|
|
|
<dt>42~62行目</dt>
|
|
<dd> value プロパティを宣言しています。TJS_BEGIN_NATIVE_PROP_DECL と TJS_END_NATIVE_PROP_DECL の両マクロには、メソッドの宣言と同じく、プロパティ名を指定します。<br />
|
|
<br />
|
|
TJS_BEGIN_NATIVE_PROP_GETTER と TJS_END_NATIVE_PROP_GETTER マクロで囲まれた場所には、ゲッターを記述することができます。ゲッター内では tTJSVariant 型である *result に値を設定するように記述します。<br />
|
|
同様に、TJS_BEGIN_NATIVE_PROP_SETTER と TJS_END_NATIVE_PROP_SETTER マクロで囲まれた場所にはセッターを記述することができます。セッター内では tTJSVariant 型である *param に設定されるべき値が格納されているので、それを使って処理をします。</dd>
|
|
|
|
|
|
<dt>64~79行目</dt>
|
|
<dd> ここでは読み出し専用プロパティを宣言しています。セッターの代わりに TJS_DENY_NATIVE_PROP_SETTER を書くことにより、読み出し専用プロパティを作ることができます。</dd></dl><br />
|
|
<br />
|
|
<br />
|
|
ネイティブクラスの登録は、ネイティブ関数の登録と同じです。以下にテストコードを例示します。<br />
|
|
<br />
|
|
|
|
<br />
|
|
<code class="bq"><span class="weak">例:</span><br /><span class="linenumber"> 1|</span> iTJSDispatch2 * global = tjsengine->GetGlobalNoAddRef();<br />
|
|
<span class="linenumber"> 2|</span> <span class="comment">// グローバルオブジェクトを取得</span><br />
|
|
<span class="linenumber"> 3|</span><br />
|
|
<span class="linenumber"> 4|</span> iTJSDispatch2 *cls = new NC_Test(); <span class="comment">// NC_Test のオブジェクトを作成</span><br />
|
|
<span class="linenumber"> 5|</span> tTJSVariant cls_var(cls); <span class="comment">// tTJSVariant 型 cls_var にオブジェクトを設定</span><br />
|
|
<span class="linenumber"> 6|</span> cls->Release(); <span class="comment">// cls を Release</span><br />
|
|
<span class="linenumber"> 7|</span><br />
|
|
<span class="linenumber"> 8|</span> TJS_THROW_IF_ERROR(<br />
|
|
<span class="linenumber"> 9|</span> global->PropSet(TJS_MEMBERENSURE, TJS_W("Test"), NULL, &cls_var, NULL));<br />
|
|
<span class="linenumber"> 10|</span> <span class="comment">// 登録</span><br />
|
|
<span class="linenumber"> 11|</span><br />
|
|
<span class="linenumber"> 12|</span> tjsengine->ExecScript(TJS_W(<br />
|
|
<span class="linenumber"> 13|</span> "var test = new Test();\n"<br />
|
|
<span class="linenumber"> 14|</span> "test.value = 5;\n"<br />
|
|
<span class="linenumber"> 15|</span> "var test2 = new Test(test.square);\n"<br />
|
|
<span class="linenumber"> 16|</span> "test2.add(3);\n"<br />
|
|
<span class="linenumber"> 17|</span> "test2.print();\n\0"),<br />
|
|
<span class="linenumber"> 18|</span> NULL, NULL, NULL); <span class="comment">// スクリプトを実行</span><br />
|
|
</code>
|
|
<br />
|
|
|
|
<br />
|
|
</div></div>
|
|
<script type="text/javascript" charset="UTF-8" src="documentid.js" ></script>
|
|
<script type="text/javascript" charset="UTF-8" src="postcontent.js" ></script>
|
|
</body>
|
|
</html>
|