Как создать функцию TCL с необязательными аргументами, используя SWIG? - PullRequest
2 голосов
/ 28 августа 2011

У меня есть простое приложение на языке c / c ++, которое имеет дополнительный интерпретатор TCL с обертками функций, сгенерированными с помощью SWIG. Для некоторых функций все аргументы являются необязательными. Как это обычно обрабатывается? Я хотел бы поддержать команду TCL, например, где любой из аргументов является необязательным, но функция C принимает фиксированные аргументы:

 //TCL command
 get_list [options] filename
   -opt1
   -opt2
   -opt3 arg1 
   -opt4 arg2
   filename

//C function
static signed get_list(bool         opt1,
                       bool         opt2,
                       char       * arg1,
                       objectType * arg2,
                       char       * fileName)

В настоящее время у меня есть что-то вроде этого:

static pList * get_list(char    * arg1=NULL,
                        char    * arg2=NULL, 
                        char    * arg3=NULL,  
                        tObject * arg4=NULL)

Это имеет много проблем, таких как принудительное указание объекта всегда последний аргумент. В документации SWIG подробно говорится о функциях C с переменными аргументами, использующими «...», но я не думаю, что это то, что мне нужно. Я бы хотел, чтобы аргументы функции C были исправлены.

1 Ответ

2 голосов
/ 30 августа 2011

Самый простой способ - обернуть процедуру Tcl снаружи, например, так:

rename get_list original.get_list
proc get_list args {
    if {[llength $args] == 0 || [llength $args] % 2 == 0} {
        error "wrong # args: ...";   # Do a proper error message here!
    }
    # Handle the required argument
    set filename [lindex $args end]
    # Initialize the defaults
    array set opts {
        -opt1 false
        -opt2 false
        -opt3 ""
        -opt4 ""
    }
    # Merge in the supplied options
    foreach {opt val} [lrange $args 0 end-1] {
        if {![info exist opts($opt)]} {
            error "unrecognized option \"$opt\""
        }
        set opts($opt) $value
    }
    # Hand off to C level...
    original.get_list $opts(-opt1) $opts(-opt2) $opts(-opt3) $opts(-opt4) $filename
}

Если у вас есть Tcl 8.6, эту последнюю передачу обслуживания лучше всего выполнить с tailcall, поэтому переписать кодвырезан из стека Tcl.Это не является жизненно важным, поскольку SWIGged код редко разрешает имена команд и переменных Tcl.

...