0

私は相対性理論で C++ を初めて使用し、TCL を初めて使用します。tValue という名前の変数を共有する 1 組のアプリケーション (C++ で 1 つ、TCL で 1 つ) を作成しようとしています。

目標は、C++ プログラムがユーザー入力を要求し、その入力を tValue に割り当てることです。次に、TCL プログラムの tValue を更新する必要があります。

私は検索して検索してきましたが、他に試してみることができません。

編集: もともと、tcl スクリプトは「メイン」C++ スレッドで実行されていましたが、C++ スレッドは tcl スクリプトが終了するのを待ちました。tcl スクリプトを呼び出す C++ コードを独自のスレッドにシフトすると、2 つのスレッドの同時実行が可能になりました (これがこれを実現する唯一の方法ですか?) が、tValue はまだ更新されていませんでした。

これらは、2 つのプログラムのソース コードです。

test.cpp

#include <tcl.h>
#include <iostream>

using namespace std;

Tcl_Interp * interp = Tcl_CreateInterp();
char * tValue = Tcl_Alloc(20);

void *thread_proc(void* x);

int main() {

    cout << "C++: INIT: " << Tcl_Init(interp) << "\n";

    cout << "C++: I'm alive, I'm alive, I'M ALIVE!!!\n";

    pthread_t t1;
    int res = pthread_create(&t1,NULL,thread_proc,NULL);

    int errLink = Tcl_LinkVar (interp, tValue, (char *) &tValue, TCL_LINK_STRING);

    cout << "C++: INTERP " << errLink << "\n";

    usleep(5000);

    cout << "C++: Well...\nC++: Has anything happened?\n";

    while (true) {
        cout << "C++: Enter a string\n";
        cin >> tValue;
        cout << "C++: You have entered " << tValue << "\n";
        Tcl_UpdateLinkedVar(interp, tValue);
    }

    return 1;
}

void *thread_proc(void* x) {
    cout << "C++ TP: Thread Launched: " << "\n";

    int errEval = Tcl_EvalFile(interp,"./test.tcl");

    cout << "C++ TP: EVAL: " << errEval << "\n";

    pthread_exit(NULL);
}

およびtest.tcl

#!/home/gc/tcl/bin/tclsh8.6

set tValue ""

puts "I'm also alive"

after 10000

puts "about to puts"

after 1000

puts $tValue

after 10000

puts "about to end"

after 1000

puts "Ended"

どんな助けでも大歓迎です、私はそれを機能させようとしてキーボードを叩いています...そして失敗しています...

4

1 に答える 1

1

これを行う正しい方法は、最初に、マルチスレッド アプリケーションに関して Tcl に弱点があることを理解することです。つまり、「アパートメント スレッド」モデルを使用するという制限があります。これは、スレッド内で行われるすべてのことは、他のスレッドから「離れて」おかなければならないことを意味します。

具体的には、インタープリターを作成するスレッドは、そのインタープリターと対話できる唯一のスレッドです。これには、すべての Tcl_xxx C API 関数の使用が含まれます。唯一の例外 (これは重要です) は、Tcl_AsyncXXX API 関数の場合です。

リンクされた変数を ACROSS THREADS で適切に使用するには、Tcl スレッドとは別に実行されている C ベースのスレッドから Tcl_UpdateLinkedVar を呼び出さないでください。代わりに、そのスレッドは Tcl_AsyncCreate() などを使用して非同期イベント トークンとハンドラーを初期化し、関連する関数を使用して Tcl スレッドで非同期ハンドラーを呼び出す必要があります。この時点で、ハンドラーは Tcl_UpdateLinkedVar() を安全に呼び出すことができます。非同期ハンドラーは、Tcl_AsyncMark() への呼び出しで使用する非同期イベント トークンを作成するスレッドで常に実行されるため、適切に動作し、Tcl が必要とするスレッド モデルのアパートメント性が保持されます。

より完全な回答をする時間があればよかったのですが、次のことを考えれば、これで生産的な軌道に乗ることができると思います。 C の 1 つのスレッドで var を更新することは、Tcl インタープリターに対して「非同期」であり、したがって、非同期メカニズムを使用して、Tcl var の更新を、使用している Tcl interp を実行しているスレッドに「ハンドオフ」する必要があります。

幸運を!

PS: これを書いているときに、Active State Tcl 8.5.15.0 for Windows のヘルプ ドキュメントを見ています。ドキュメントは非常に優れており、ほとんどがクロスプラットフォームに適用可能です。少なくとも 1 つのコンパニオン リファレンスとしてお勧めします。

于 2014-10-11T19:18:36.397 に答える