To create a C extension loadable by tclsh is quite easy. However, direction for doing it is well hidden in various books especially passing C array of struct which is commonly required by engineering application. As an example, I'll describe here how to wrap the kiss_fft library for tclsh interpreter using Tcl C API calls. I've also tried to use SWIG, and it seems to be next to impossible to use it to pass array of C struct. The basic idea is to represent C struct as Tcl list and use various Tcl C API to convert Tcl_Obj to native C data types. <>Engineering // written by Long To, 10/24/2015 to interface with TCL. note: inverse FFT needs to be scaled down by FFT length #include "kiss_fft.h" #include // following declaration is needed for the package to detect the ???_Init() function __declspec(dllexport) int Kiss_fft_Init(Tcl_Interp *); int Kiss_fftCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Kiss_fftrCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]); int Kiss_fft_Init(Tcl_Interp *interp) { if(Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { return TCL_ERROR; } if (Tcl_PkgProvide(interp, "Kiss_fft", "1.1") == TCL_ERROR) return TCL_ERROR; Tcl_CreateObjCommand(interp, "kiss_fft", Kiss_fftCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); Tcl_CreateObjCommand(interp, "kiss_fftr", Kiss_fftrCmd, (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL); return TCL_OK; } int Kiss_fftCmd(ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { if (objc != 3) { Tcl_WrongNumArgs(interp, objc, objv, " ?inverse? ?fin?"); return TCL_ERROR; } int count, inverse; Tcl_Obj *list_in = objv[2]; // extract the 1st arg of the kiss_fft command as an integer: 0 for foward transform, 1 for inverse transform if (Tcl_GetIntFromObj(interp, objv[1], &inverse) != TCL_OK) { Tcl_AppendResult(interp, " Couldn't get direction of transform"); return TCL_ERROR; } if (Tcl_ListObjLength(interp, list_in, &count) != TCL_OK) { Tcl_AppendResult(interp, " Couldn't get fin length"); return TCL_ERROR; } int nfft = count; kiss_fft_cpx *fin = (kiss_fft_cpx *)malloc(sizeof(kiss_fft_cpx) * nfft); kiss_fft_cpx *fout = (kiss_fft_cpx *)malloc(sizeof(kiss_fft_cpx) * nfft); Tcl_Obj *real; // individual element of Tcl_Obj double represent the real part of the complex number Tcl_Obj *imag; // individual element of Tcl_Obj double represent the imaginary part of the complex number Tcl_Obj *L; // inner sublist of outer list list_in for (size_t i=0; i