Ошибка сегментации при создании пользовательского драйвера канала tcl

Я пытаюсь создать собственный канал 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. Мне нужно использовать канал только для получения вывода интерпретатора. Какие функции мне здесь не нужно реализовывать и правильно ли это направление для решения проблемы.


person Ashot    schedule 23.07.2013    source источник
comment
Исходный код Tcl доступен по адресу core.tcl.tk.   -  person Johannes Kuhn    schedule 23.07.2013
comment
@JohannesKuhn, как мне найти реализацию Tcl_CreateChannel there?   -  person Ashot    schedule 23.07.2013
comment
core.tcl.tk/tcl/artifact/   -  person Johannes Kuhn    schedule 23.07.2013


Ответы (1)


При работе на этом уровне рекомендуется загрузить исходный код в Tcl. Я не уверен, какую версию вы используете, но все официальные дистрибутивы исходного кода очень далекой давности находятся на система распространения файлов SourceForge; выберите точное совпадение с версией, которая у вас есть.

Создание пользовательского драйвера канала непросто. Это связано со значительной сложностью, и не очень хорошо документировано, какие «методы» внутри типа драйвера канала являются обязательными, а какие необязательными. (Это не методы C++ в классе — Tcl — это чистый код C по причинам, слишком длинным, чтобы вдаваться в них здесь, — но они функционируют концептуально схожим образом.)

Если мы посмотрим на документацию для Tcl_CreateChannel, мы увидим (довольно далеко вниз по этой странице) определение структуры типа канала. Структура типа канала должна быть статически размещена (реализация Tcl строго предполагает, что он никогда не меняет местоположение), а следующие поля должны быть установлены на что-то значимое:

  • typeName — это имя типа канала, полезно для отладки!
  • version — это версия типа канала; вы должны установить его на последнюю версию, поддерживаемую вашим целевым исходным уровнем. (Рекомендуется использовать как минимум TCL_CHANNEL_VERSION_2, иначе все усложнится.)
  • closeProc или close2Proc — каналы должны закрываться, но у вас есть два способа сделать это. Двунаправленные каналы должны использовать close2Proc, но это не обязательно.
  • inputProc — Нужен, только если вы читаете; позаботьтесь об этом правильно.
  • outputProc — Нужен, только если вы пишете; позаботьтесь об этом правильно.
  • watchProc — Вызывается, чтобы указать драйверу канала установить себя в систему событий, чтобы получать подходящие события (как указано в предоставленной битовой маске). Каналы, у которых нет поддерживающих дескрипторов ОС, используют события таймера или просто никогда не генерируют события (в этом случае они никогда не станут доступными для чтения или записи с точки зрения fileevent).

Глядя на ваш код, я вижу, что вам не хватает watchProc. Я знаю, что это сложно понять (честно говоря, не так много людей пишут драйверы каналов, поэтому документация не очень тщательно «проверена»), но это действительно необходимо.

person Donal Fellows    schedule 23.07.2013
comment
Спасибо за ответ. И что вы предлагаете о получении результатов интерпретатора. Я работаю над этой проблемой долгое время и пробовал много подходов. Возможно ли это сделать? - person Ashot; 24.07.2013
comment
@Ashot «Получение результатов интерпретатора» имеет, на мой взгляд, несколько возможных значений. Что вы имеете в виду? Каков вариант использования? - person Donal Fellows; 24.07.2013
comment
Мне нужно показать это в окне графического интерфейса. По умолчанию он печатает вывод в оболочке. У меня есть консольный виджет, который принимает команды от пользователя и выполняет их. Мне также нужно показать вывод команды в виджете консоли. - person Ashot; 24.07.2013