C/C++命令接口为Tclshell的工具如何开发?
How to develop tool in C/C++ whose command interface is Tcl shell?
假设需要开发一个用C/C++编写并具有Tcl命令行界面的工具X,步骤或方法是什么?
我知道 Tcl C API 可以通过为它编写 C 扩展来扩展 Tcl。
通常,SWIG(简化包装器和界面生成器)是必经之路。
SWIG HOMEPAGE
这样,您可以在C/C++中编写代码并定义要公开的接口。
假设您有一些要添加到 Tcl 中的 C 函数:
/* File : example.c */
#include <time.h>
double My_variable = 3.0;
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
int my_mod(int x, int y) {
return (x%y);
}
char *get_time()
{
time_t ltime;
time(<ime);
return ctime(<ime);
}
现在,为了将这些文件添加到您喜欢的语言中,您需要编写一个 "interface file" 作为 SWIG 的输入。这些 C 函数的接口文件可能如下所示:
/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
在 UNIX 提示符下,键入以下内容:
unix % swig -tcl example.i
unix % gcc -fpic -c example.c example_wrap.c \
-I/usr/local/include
unix % gcc -shared example.o example_wrap.o -o example.so
unix % tclsh
% load ./example.so example
% puts $My_variable
3.0
% fact 5
120
% my_mod 7 3
1
% get_time
Sun Feb 11 23:01:07 2018
swig 命令生成一个文件 example_wrap.c,应编译该文件并将其与程序的其余部分链接。在这种情况下,我们已经构建了一个可动态加载的扩展,可以使用 'load' 命令将其加载到 Tcl 解释器中。
你想要做的是嵌入 Tcl(完全是一个受支持的用例;Tcl 记得它是一个 C 库)但仍在做一些事情 tclsh-like .最简单的方法是:
获取 tclAppInit.c
的副本(例如,this 是我写这篇文章时 Tcl 8.6 源代码树中的当前副本)并修改它,可能是通过放置代码来注册您的额外内容Tcl_AppInit()
函数中的命令、linked 变量等;你可能 trim 一堆东西就足够了。然后构建 link 直接针对 Tcl 库( 没有 存根)以有效地获得具有额外功能的自定义 tclsh。
如果您对交互式使用不感兴趣,您可以更广泛地使用 Tcl 的 API。 non-interactive使用的核心是:
// IMPORTANT: Initialises the Tcl library internals!
Tcl_FindExecutable(argv[0]);
Tcl_Interp *interp = Tcl_CreateInterp();
// Register your custom stuff here
int code = Tcl_Eval(interp, "your script");
// Or Tcl_EvalFile(interp, "yourScriptFile.tcl");
const char *result = Tcl_GetStringResult(interp);
if (code == TCL_ERROR) {
// Really good idea to print out error messages
fprintf(stderr, "ERROR: %s\n", result);
// Probably a good idea to print error traces too; easier from in Tcl
Tcl_Eval(interp, "puts stderr $errorInfo");
exit(1);
}
// Print a non-empty result
if (result[0]) {
printf("%s\n", result);
}
这就是您所需要的一切,除非您进行交互式使用,这就是 Tcl_Main()
变得真正有用的时候(它处理了很多额外的繁琐细节),示例 tclAppInit.c
(提到上面)展示了如何使用。
假设需要开发一个用C/C++编写并具有Tcl命令行界面的工具X,步骤或方法是什么?
我知道 Tcl C API 可以通过为它编写 C 扩展来扩展 Tcl。
通常,SWIG(简化包装器和界面生成器)是必经之路。 SWIG HOMEPAGE
这样,您可以在C/C++中编写代码并定义要公开的接口。
假设您有一些要添加到 Tcl 中的 C 函数:
/* File : example.c */
#include <time.h>
double My_variable = 3.0;
int fact(int n) {
if (n <= 1) return 1;
else return n*fact(n-1);
}
int my_mod(int x, int y) {
return (x%y);
}
char *get_time()
{
time_t ltime;
time(<ime);
return ctime(<ime);
}
现在,为了将这些文件添加到您喜欢的语言中,您需要编写一个 "interface file" 作为 SWIG 的输入。这些 C 函数的接口文件可能如下所示:
/* example.i */
%module example
%{
/* Put header files here or function declarations like below */
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
%}
extern double My_variable;
extern int fact(int n);
extern int my_mod(int x, int y);
extern char *get_time();
在 UNIX 提示符下,键入以下内容:
unix % swig -tcl example.i
unix % gcc -fpic -c example.c example_wrap.c \
-I/usr/local/include
unix % gcc -shared example.o example_wrap.o -o example.so
unix % tclsh
% load ./example.so example
% puts $My_variable
3.0
% fact 5
120
% my_mod 7 3
1
% get_time
Sun Feb 11 23:01:07 2018
swig 命令生成一个文件 example_wrap.c,应编译该文件并将其与程序的其余部分链接。在这种情况下,我们已经构建了一个可动态加载的扩展,可以使用 'load' 命令将其加载到 Tcl 解释器中。
你想要做的是嵌入 Tcl(完全是一个受支持的用例;Tcl 记得它是一个 C 库)但仍在做一些事情 tclsh-like .最简单的方法是:
获取 tclAppInit.c
的副本(例如,this 是我写这篇文章时 Tcl 8.6 源代码树中的当前副本)并修改它,可能是通过放置代码来注册您的额外内容Tcl_AppInit()
函数中的命令、linked 变量等;你可能 trim 一堆东西就足够了。然后构建 link 直接针对 Tcl 库( 没有 存根)以有效地获得具有额外功能的自定义 tclsh。
如果您对交互式使用不感兴趣,您可以更广泛地使用 Tcl 的 API。 non-interactive使用的核心是:
// IMPORTANT: Initialises the Tcl library internals!
Tcl_FindExecutable(argv[0]);
Tcl_Interp *interp = Tcl_CreateInterp();
// Register your custom stuff here
int code = Tcl_Eval(interp, "your script");
// Or Tcl_EvalFile(interp, "yourScriptFile.tcl");
const char *result = Tcl_GetStringResult(interp);
if (code == TCL_ERROR) {
// Really good idea to print out error messages
fprintf(stderr, "ERROR: %s\n", result);
// Probably a good idea to print error traces too; easier from in Tcl
Tcl_Eval(interp, "puts stderr $errorInfo");
exit(1);
}
// Print a non-empty result
if (result[0]) {
printf("%s\n", result);
}
这就是您所需要的一切,除非您进行交互式使用,这就是 Tcl_Main()
变得真正有用的时候(它处理了很多额外的繁琐细节),示例 tclAppInit.c
(提到上面)展示了如何使用。