Python 我可以使用Tkinter创建Tcl交互式shell吗?

Python 我可以使用Tkinter创建Tcl交互式shell吗?,python,tkinter,tcl,ctypes,Python,Tkinter,Tcl,Ctypes,我目前正在使用Python3中的ctypes来创建一个Tcl应用程序,它封装了一个用Python编写的库 from ctypes import * import sys tcl = cdll.LoadLibrary("libtcl.so") TCL_OK = 0 TCL_ERROR = 1 def say_hello(cdata: c_void_p, interp: c_void_p, argc: c_int, argv: POINTER(c_char_p)) -> int:

我目前正在使用Python3中的ctypes来创建一个Tcl应用程序,它封装了一个用Python编写的库

from ctypes import *
import sys

tcl = cdll.LoadLibrary("libtcl.so")

TCL_OK = 0
TCL_ERROR = 1

def say_hello(cdata: c_void_p, interp: c_void_p, argc: c_int, argv: POINTER(c_char_p)) -> int:
    "This function wraps some functionality that is written in Python"
    print("hello, world")
    return TCL_OK

# useful type definitions
Tcl_AppInitProc = CFUNCTYPE(c_int, c_void_p)
Tcl_CmdProc = CFUNCTYPE(c_int, c_void_p, c_void_p, c_int, POINTER(c_char_p))
Tcl_CmdDeleteProc = CFUNCTYPE(None, c_int)

def app_init(interp: c_void_p) -> int:
    # initialize the interpreter
    tcl.Tcl_Init.restype = c_int
    tcl.Tcl_Init.argtypes = [c_void_p]
    if tcl.Tcl_Init(interp) == TCL_ERROR:
        return TCL_ERROR

    # create custom commands
    tcl.Tcl_CreateCommand.restype = c_void_p
    tcl.Tcl_CreateCommand.argtypes = [c_void_p, c_char_p, Tcl_CmdProc, c_int, Tcl_CmdDeleteProc]
    tcl.Tcl_CreateCommand(interp, b"say_hello", Tcl_CmdProc(say_hello), 0, Tcl_CmdDeleteProc(0))

    return TCL_OK

if __name__ == "__main__":
    # initialize argv
    Argv = c_char_p * (1 + len(sys.argv))
    argv = Argv(*(bytes(arg, "utf-8") for arg in sys.argv), 0)

    # summon the chief interpreter
    tcl.Tcl_Main.argtypes = [c_int, POINTER(c_char_p), Tcl_AppInitProc]
    tcl.Tcl_Main(len(sys.argv), argv, Tcl_AppInitProc(app_init))
从命令行来看,这就像一个带有额外命令的Tcl解释器,这正是我想要的。它解析sys.argv,既可以作为交互式shell运行,也可以运行Tcl脚本

bash$python3 hello.py
%打招呼
你好,世界
%ls
foo.tcl hello.py
%出口
bash$cat foo.tcl
打招呼
bash$python3 hello.py foo.tcl
你好,世界
猛击$
但是,我知道Python已经在tkinter模块中提供了一个Tcl解释器。相反,我想使用它,因为它已经有了一个很好的Python包装API,可以节省我对CType的一些费解

我可以很容易地创建一个解释器和添加命令

from tkinter import *

def say_hello():
    print("hello, world")

if __name__ == "__main__":
    tcl = Tcl()
    tcl.createcommand("say_hello", say_hello)
    tcl.eval("say_hello")
但是我找不到任何方法来调用
Tcl\u Init
Tcl\u Main
,没有它们,我就无法以交互方式运行它。虽然我不太关心命令行解析器,但尝试在Python中复制Tcl interactive shell及其所有功能,比如像运行外部程序一样运行Tcl命令(如上例中的
ls
),需要做大量工作。如果这是我唯一的选择,我会坚持使用ctypes


有没有任何方法,甚至是一种不成熟或不受支持的方法,来运行Tkinter附带的Tcl解释器作为一个交互式shell?

Tcl\u Main()
中实现的REPL真的很简单;您可以在几行Tcl中实现(稍微精简)版本:

set cmd ""
set prompt "% "
while true {
    # Prompt for input
    puts -nonewline $prompt
    flush stdout
    if {[gets stdin line] < 0} break

    # Handle multiline commands
    append cmd $line "\n"
    if {![info complete $cmd]} {
        set prompt ""
        continue
    }
    set prompt "% "

    # Evaluate the command and print error/non-empty results
    if {[catch $cmd msg]} {
        puts stderr "Error: $msg"
    } elseif {$msg ne ""} {
        puts $msg
    }
    set cmd ""
}
set cmd“”
设置提示“%”
虽然是真的{
#提示输入
puts-nonewline$提示符
冲洗冲洗液
如果{[gets stdin line]<0}中断
#处理多行命令
追加cmd$行“\n”
如果{![info complete$cmd]}{
设置提示“”
持续
}
设置提示“%”
#评估命令并打印错误/非空结果
如果{[catch$cmd msg]}{
将stderr放入“错误:$msg”
}其他{$msg ne”“}{
放$msg
}
设置cmd“”
}

您所需要做的就是在Python代码中的Tcl解释器中运行它。您还可以在Python中重新实现大部分REPL;此时,您真正需要Tcl的只有
info complete$cmd
(测试输入缓冲区中是否有完整的命令)和
catch$cmd msg
(在Tcl解释器中评估输入缓冲区并捕获结果和错误)。

Tcl
Tk
相同
tkinter
imports
\u tkinter
这是一部分,请查看您缺少的函数。谢谢,我不知道
info complete
。我将进一步研究这个问题,我将其标记为已接受,因为它看起来像我将要做的,但我仍然有兴趣了解其他方法!