我正在尝试创建自定义tcl通道并使用它来获取tcl Interpreter的输出。我添加了Tcl_ChannelType的一些功能的实现,但我得到了段错误。
#include <tcl.h>
#include <iostream>
int driverBlockModeProc(ClientData instanceData, int mode) {
std::cout << "driverBlockModeProc\n";
return 0;
}
int driverCloseProc(ClientData instanceData, Tcl_Interp *interp) {
std::cout << "driverCloseProc\n";
return 0;
}
int driverInputProc(ClientData instanceData, char* buf, int bufSize, int *errorCodePtr) {
std::cout << "driverInputProc\n";
return 0;
}
int driverOutputProc(ClientData instanceData, const char* buf, int toWrite, int *errorCodePtr) {
std::cout << "driverOutputProc\n";
return 0;
}
int main() {
Tcl_ChannelType *typePtr = new Tcl_ChannelType;
typePtr->blockModeProc = driverBlockModeProc;
typePtr->outputProc = driverOutputProc;
typePtr->closeProc = driverCloseProc;
typePtr->inputProc = driverInputProc;
typePtr->seekProc = NULL;
typePtr->setOptionProc = NULL;
typePtr->getOptionProc = NULL;
typePtr->watchProc = NULL;
typePtr->getHandleProc = NULL;
typePtr->close2Proc = NULL;
typePtr->blockModeProc = NULL;
typePtr->flushProc = NULL;
typePtr->handlerProc = NULL;
typePtr->wideSeekProc = NULL;
typePtr->threadActionProc = NULL;
ClientData data = new char[200];
Tcl_CreateChannel(typePtr, "im_chanel", data, TCL_WRITABLE | TCL_READABLE);
}
我无法调试segfault,因为它的源不可用。我认为segfault是因为调用了一个NULL函数。我只需要使用通道来获取解释器的输出。我不需要在这里实现哪些功能,是解决问题的正确方向。
答案 0 :(得分:2)
建议您在此级别工作时将源代码下载到Tcl。我不确定你使用的是什么版本,但是源代码的所有官方发行版都可以追溯到the SourceForge file distribution system;选择你所拥有版本的完全匹配。
创建自定义渠道驱动程序不很容易。涉及到大量的复杂性,并且没有特别详细记录通道驱动程序类型中的“方法”是强制性的以及什么是可选的。 (它们不是类中的C ++方法 - Tcl是纯粹的C代码,原因太久了 - 但它们在概念上类似的方式起作用。)
如果我们查看Tcl_CreateChannel
的文档,我们会看到(在该页面下很长的路径)通道类型结构的定义。通道类型结构应该静态分配(Tcl的实现非常强烈地假设它永远不会改变位置)并且必须将以下字段设置为有意义的东西:
typeName
- 这是通道类型的名称,对调试很有用!version
- 这是频道类型的版本;您应该将其设置为目标源级别支持的最新版本。 (建议至少使用TCL_CHANNEL_VERSION_2
或者事情变得更复杂。)closeProc
或 close2Proc
- 频道必须可以关闭,但您有两种方法可以选择。双向渠道应使用close2Proc
,但并非严格要求。inputProc
- 只有在您阅读时才需要;注意正确处理这个问题。outputProc
- 只有在你写作时才需要;注意正确处理这个问题。watchProc
- 调用告诉通道驱动程序将自身安装到事件系统中以便接收适当的事件(按照提供的位掩码的指示)。没有支持OS处理的通道使用计时器事件,或者根本就不会实际生成事件(在这种情况下,它们永远不会从fileevent
的角度变得可读或可写。)查看您的代码,我发现您错过了watchProc
。我知道很难看到(没有多少人写通道驱动程序,说实话,所以文档不是很难“测试”)但是它确实是必要的。