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 show 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. Anyone with knowledge of how to do this using SWIG, please share it here, Thanks! The basic idea is to represent C struct as Tcl list and then use various Tcl C API to convert Tcl_Obj to native C data types. call the kiss_fft then convert the output array of struct back to Tcl list before passing it back to Tcl interpreter. Kiss_fft is an open source library for doing mix-radix Fast Fourier Transform. it can be downloaded from its homepage at: http://sourceforge.net/projects/kissfft I've created two C extension Tcl commands, kiss_fft for complex data input and kiss_fftr for real data input in this post; the rest of the library can be easily made available as Tcl commands. I hope by seeing an example of how to create Tcl extension command using C APIs will help those of us who have no idea how to start solving problem like this. as you can see, it's rather simple to extend the Tcl if shown by some example. Happy coding! <>Engineering, FFT, Fourier Transform ====== // 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 in Windows using MSVC compiler 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