0

カスタム tcl チャネルを作成し、それを使用して tcl インタープリターの出力を取得しようとしています。Tcl_ChannelType のいくつかの関数の実装を追加しましたが、segfault が発生しています。

#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 をデバッグできません。セグメンテーション違反は、NULL である関数が呼び出されたためだと思います。インタープリターの出力を取得するためにチャネルを使用するだけです。ここで実装する必要のない機能と、問題を解決するための正しい方向です。

4

1 に答える 1

2

このレベルで作業する場合は、ソースを Tcl にダウンロードすることをお勧めします。あなたが使用しているバージョンはわかりませんが、ソースの公式ディストリビューションはすべてSourceForge ファイル ディストリビューション システム上にあります。持っているバージョンに完全に一致するものを選択してください。

カスタム チャネル ドライバーを作成するのは簡単ではありません。これにはかなりの複雑さが伴い、チャネル ドライバ タイプ内のどの "メソッド" が必須で、何がオプションであるかについて特に十分に文書化されていません。(これらはクラス内の C++ メソッドではありません — Tcl は純粋な C コードであり、その理由はここでは説明するには長すぎます — しかし、概念的には同様の方法で機能します。)

のドキュメントを見ると、Tcl_CreateChannel(そのページのかなり下の方に) チャネル型構造の定義が表示されます。チャネル タイプ構造体は静的に割り当てる必要があり(Tcl の実装では、場所が変更されないことを非常に強く前提としています)、次のフィールドを意味のあるものに設定する必要があります。

  • typeName— これはチャネル タイプの名前で、デバッグに役立ちます。
  • version— これはチャネル タイプのバージョンです。ターゲット ソース レベルでサポートされている最新バージョンに設定する必要があります。(少なくとも使用することをお勧めします。そうしTCL_CHANNEL_VERSION_2ないと、かなり複雑になります。)
  • closeProc または close2Proc— チャネルは閉じることができる必要がありますが、それを行う方法には 2 つの選択肢があります。双方向チャネルを使用するclose2Proc必要がありますが、厳密には必須ではありません。
  • inputProc— 読んでいる場合にのみ必要です。これを正しく処理するように注意してください。
  • outputProc— あなたが書いている場合にのみ必要です。これを正しく処理するように注意してください。
  • watchProc— (提供されたビットマスクによって指示された) 適切なイベントを受信するために、チャネル ドライバーがイベント システムに自身をインストールするように指示するために呼び出されます。バッキング OS ハンドルを持たないチャネルは、タイマー イベントを使用するか、単に実際にイベントを生成することはありません (この場合、 の観点から読み取りまたは書き込み可能になることはありませんfileevent)。

あなたのコードを見ると、watchProc. わかりにくいことは承知しています (正直に言うと、多くの人がチャネル ドライバーを作成していないため、ドキュメントの "テスト" はそれほど難しくありません) が、これは本当に必要なことです。

于 2013-07-23T09:36:29.380 に答える