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 command, kiss_fft and kiss_fftr 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. <>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