0

我是 C++ 的相对论新手,对 TCL 非常陌生。我正在尝试编写一对共享一个名为 tValue 的变量的应用程序(一个在 C++ 中,一个在 TCL 中)。

目标是 C++ 程序要求用户输入并将该输入分配给 tValue。然后 TCL 程序应该更新它的 tValue。

我一直在寻找和寻找,但找不到其他可以尝试的东西。

编辑:最初 tcl 脚本是在“主”C++ 线程中执行的,但 C++ 线程等待 tcl 脚本完成。将调用 tcl 脚本的 c++ 代码转移到它自己的线程中确实允许两个线程同时执行(这是实现这一点的唯一方法吗?),但 tValue 仍然没有更新

这些是这两个程序的源代码:

测试.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 在多线程应用程序方面有一个弱点,或者应该说是一个限制:它使用“Apartment threading”模型。这意味着在一个线程中完成的所有事情都必须与任何其他线程“分开”。

具体来说,创建解释器的线程是唯一可以与该解释器交互的线程。这包括使用所有 Tcl_xxx C API 函数。唯一的例外,这很重要,是 Tcl_AsyncXXX API 函数。

为了正确使用 ACROSS THREADS 链接变量,您不会从与您的 Tcl 线程分开运行的基于 C 的线程调用 Tcl_UpdateLinkedVar。相反,该线程应该使用 Tcl_AsyncCreate() 等初始化异步事件令牌和处理程序,并使用相关函数调用 Tcl 线程中的异步处理程序,此时处理程序可以安全地调用 Tcl_UpdateLinkedVar()。因为异步处理程序将始终在创建异步事件令牌的线程中执行,您将在调用 Tcl_AsyncMark() 时使用该令牌,它将正常工作,并且将保留 Tcl 所需的线程模型的单元性。

我希望我有更多时间给出更全面的答案,但我认为这会让你走上一条富有成效的轨道,如果你考虑一下:在一个线程中更新 var,在 C 中,对于 Tcl 解释器是“异步的”,并且因此,您必须使用异步机制将 Tcl var 的更新“移交”给运行您正在使用的 Tcl interp 的线程。

祝你好运!

PS:我在写这篇文章时正在查看 Active State Tcl 8.5.15.0 for Windows 帮助文档。文档非常好,大多跨平台适用;我推荐它至少作为你经常使用的伴侣参考之一。

于 2014-10-11T19:18:36.397 回答