2017-10-19 8 views
0

私はTcl_CreateObjCommandを使って登録したcコードで書かれた新しいtclコマンドを実装し、このcコードの中でTcl_Evalを呼び出して連想配列を作成し、それを変数tmpに格納するコードを含む文字列を評価します。 Tcl_eval()で作成されたこのtmp変数を、C関数の戻り結果オブジェクトとして設定するにはどうすればよいですか?tclライブラリ:tcl_eval()を使用してcコードのtclコマンド拡張の戻り結果を設定する方法は?

例:ところで上記の作品に

TCL> set x [MyCommand] 

TCL> puts "$x(key1)" 
value1 # Currently an Error and not set 

TCL> puts "$x(key2)" 
value2 # Currently and Error and not set 

:私は上記のC-拡張子を持つTclインタープリタを実行すると

int MyCommand(
    ClientData clientData, 
    Tcl_Interp* interp, 
    int   argc, 
    char*  argv[]) 
{ 

    int rc = Tcl_Eval(interp, 
     "array set tmp [list {key1} {value1} {key2} {value2}]"); 
    if (rc != TCL_OK) { 
     return rc; 
    } 

    //??? 
    Tcl_SetObjResult(interp, ?? tmp variable from eval??); 
    return TCL_OK; 
} 

が、私はこの結果を見ることを期待します。ちょうど私がそれをしたい方法ではありません。私が入力した場合たとえば、:

TCL> set x [MyCommand] 

TCL> puts "$tmp(key1)" 
value1 # Its Works! Except, I didn't want to set a global variable tmp 

TCL> puts "$tmp(key2)" 
value2 # Its Works! Except, I didn't want to set a global variable tmp 

(代わりにTMPを設定するには、たぶん、そのA「機能」??)とにかく、私はまだそれをprocの「リターン」のメカニズムを使用して値を返すことによって、正しい方法を仕事をしたいです。

「Tclライブラリ」のドキュメントでは、tcl_evalの場合、他のコマンドを評価するためにネストされた呼び出しを行うことができますので、cclient-extensionのTcl_Eval()を呼び出すことは正当です。私はちょうどTcl_Evalからのオブジェクト結果をc-拡張手順のオブジェクトを "返す"にコピーする方法を知らない。

答えて

2

ここに2つの問題があります。配列の値は配列ではないため、コマンドの戻り値を配列の値に設定することはできません。配列は、文字列でインデックスされた変数の集合です。それはよくある誤解です。配列の要素の値を返すことができます。適切なTcl値であるキー/値マップが必要な場合は、辞書を検討してください。辞書は値であり、コマンドの値として返すことができます。

なぜ2番目の問題はTcl_Eval()を使用して配列を作成するのですか? Tcl_SetVar()またはいくつかのバリエーションの1つを使用して配列を構築する方がはるかに簡単です。

2

char*の値を最初に使用している場合は、Tcl_SetVar2(2つの部分として変数名が使用されるため)という名前の配列を使用することをお勧めします。

Tcl_SetVar2(interp, "tmp", "key1", "value1", 0); 
Tcl_SetVar2(interp, "tmp", "key2", "value2", 0); 

慣用的に、呼び出し側がへの書き込みに何の変数を伝えることができますようにあなたは、引数として、あなたのCコマンドの実装に引数として渡された名前を使用したい、あなたがチェックしたいと思いますあまりにも結果:

int MyCommand(
    ClientData clientData, 
    Tcl_Interp* interp, 
    int   argc, 
    char*  argv[]) 
{ 
    // Missing: check # of arguments 

    if (Tcl_SetVar2(interp, argv[1], "key1", "value1", 0) == NULL) 
     return TCL_ERROR; 
    if (Tcl_SetVar2(interp, argv[1], "key2", "value2", 0) == NULL) 
     return TCL_ERROR; 
    return TCL_OK; 
} 

あなたはこのようにそれを呼びたい:

MyCommand x 
# It has no meaningful result. 

puts $x(key1) 
puts $x(key2) 
関連する問題