[NEM] A question on the chat was how to do a simple "Hello, World!" type [command] or [extension], using [Tcl]'s [C] API. This is dead easy, and is probably a good place to start for newbies. So here is the code. /* * hello.c -- * * A dirt simple Tcl C extension. */ #include static int Hello_Cmd( ClientData cdata, Tcl_Interp *interp, int objc, Tcl_Obj * CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewStringObj("Hello, World!", -1)); return TCL_OK; } /* * Hello_Init -- * * Called when Tcl [load]'s your extension. */ int Hello_Init(Tcl_Interp *interp) { if (Tcl_InitStubs(interp, TCL_VERSION, 0) == 0L) { return TCL_ERROR; } Tcl_CreateObjCommand(interp, "hello", Hello_Cmd, NULL, NULL); Tcl_PkgProvide(interp, "Hello", "1.0"); return TCL_OK; } ---- [RS]: Wouldn't it be simpler to put the implementation of Hello_Cmd at top (to avoid a forward declaration)? And also, so as not to clutter the symbol table, make it ''static'' so it's only visible inside this file? [NEM]: You could do. I personally prefer having the Init function as the first function in the file, but I could be persuaded otherwise. Added the static declarations, thanks. [NEM]: I've buckled to pressure and removed the prototype -- looks clearer, certainly for this example. [SO]: Added call to Tcl_PkgProvide - 8/8/05 ---- Compile with: gcc -shared -DUSE_TCL_STUBS hello.c -o libhello.so -ltclstub8.4 and you should end up with a shared library that you can [[ [load] ]] into [tclsh], and then call the "hello" command. Lots of details left out - consult the [man page]s, books and more extensive docs elsewhere. Also see the [sampleextension]. Oh, and adapt the compiler line to your OS/compiler combination. ''For those who come from a mostly [scripting] background, such adaption can be quite some work. The following should do the trick in [Mac OS X]:'' gcc -dynamiclib -DUSE_TCL_STUBS hello.c /Library/Frameworks/Tcl.framework/libtclstub8.4.a -o libhello.dylib ''There is probably a better way than giving the full path to the Tcl [stubs] library, though.'' [PR] ''This is the Mac OS X way:'' gcc -dynamiclib -DUSE_TCL_STUBS hello.c -framework Tcl -o libhello.dylib Note, if you do it this way - using the -framework - you are linking to the Tcl dylib, not the Tcl stub library. For an extension, it is better to link to the stub library if you can. The only way to do that is as above, though a more formally correct version is: gcc -dynamiclib -DUSE_TCL_STUBS hello.c -L/Library/Frameworks/Tcl.framework -ltclstub8.4 -o libhello.dylib To load, remember to do: tclsh8.4 % load ./libhello[info sharedlibextension] so that Tcl finds it ([[load]] doesn't look in the current dir unless told to). ---- '''Using namespaces''' [TR] - Many extensions nowadays create their commands in a [namespace]. To do the above example using namespaces, you only need two more lines in the code: Hello_Init(Tcl_Interp *interp) { Tcl_Namespace *nsPtr; /* pointer to hold our own new namespace */ /* Note that I use '== NULL' here instead of '== 0L', since that seems more correct */ if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) { return TCL_ERROR; } /* create the namespace named 'hello' */ nsPtr = Tcl_CreateNamespace(interp, "hello", NULL, NULL); if (nsPtr == NULL) { return TCL_ERROR; } /* just prepend the namespace to the name of the command. Tcl will now create the 'hello' command in the 'hello' namespace so it can be called as 'hello::hello' */ Tcl_CreateObjCommand(interp, "hello::hello", Hello_Cmd, NULL, NULL); Tcl_PkgProvide(interp, "Hello", "1.0"); return TCL_OK; } Note that compiling the example with the Tcl_CreateNamespace() function will give you are warning using Tcl 8.4 (at least until 8.4.12) and no warning using Tcl 8.5. This is because Tcl_CreasteNamespace is an internal function in 8.4 and public in 8.5. So compiling with Tcl 8.4 you should add the line '#include ' to the C source if you want to avoid the warning. But the code code works regardless of this directive. [CLN] - In my extension, I put the namespace in a #define so I have: #define NS "hello" ... nsPtr = Tcl_CreateNamespace(interp, NS, NULL, NULL); ... Tcl_CreateObjCommand(interp, NS "::hello", Hello_Cmd, NULL, NULL); (Note that there's no operator between the NS and the "::hello" for Tcl_CreateObjCommand(), C very nicely catenates adjacent literal strings.) ---- There is also a sample with [Windows] build instructions at [Building Tcl DLL's for Windows] ---- [Category Tutorial] - [Category Foreign Interfaces]