Version 4 of Writing extensions for stubs and pre-stubs Tcl

Updated 2005-06-01 14:04:39

David Gravereaux gave this code on news:comp.lang.tcl for writing code which will compile for both stubs-enabled, and pre-stubs (8.0) Tcl, both using the Tcl_Obj interface (so nothing prior to 8.0). Perhaps people can add extras for different compilers/platforms...

 8.0 and 8.1+ have a different interface for extensions. Please pardon the overdose of macros, but this works and is very aggressive:


 #include <tcl.h>

 // We need at least the Tcl_Obj interface that was started in 8.0
 #if TCL_MAJOR_VERSION < 8
 #   error "we need Tcl 8.0 or greater to build this"

 // Check for Stubs compatibility when asked for it.
 #elif defined(USE_TCL_STUBS) && TCL_MAJOR_VERSION == 8 && \
        (TCL_MINOR_VERSION == 0 || \
        (TCL_MINOR_VERSION == 1 && TCL_RELEASE_LEVEL != TCL_FINAL_RELEASE))
 #   error "Stubs interface doesn't work in 8.0 and alpha/beta 8.1; only 8.1.0+"
 #endif


 #ifdef _MSC_VER
    // Only do this when MSVC++ is compiling us.
 #   ifdef USE_TCL_STUBS
        // Mark this .obj as needing tcl's Stubs library.
 #       pragma comment(lib, "tclstub" \
            STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) ".lib")
 #       if !defined(_MT) || !defined(_DLL) || defined(_DEBUG)
            // This fixes a bug with how the Stubs library was compiled.
            // The requirement for msvcrt.lib from tclstubXX.lib should
            // be removed.
 #           pragma comment(linker, "-nodefaultlib:msvcrt.lib")
 #       endif
 #   else
    // Mark this .obj needing the import library
 #   pragma comment(lib, "tcl" \
        STRINGIFY(JOIN(TCL_MAJOR_VERSION,TCL_MINOR_VERSION)) ".lib")
 #   endif
 #endif


 #undef TCL_STORAGE_CLASS
 #define TCL_STORAGE_CLASS DLLEXPORT

 EXTERN int
 Livemsg_Init(Tcl_Interp *interp)
 {
  int code;

 #ifdef USE_TCL_STUBS
    if (Tcl_InitStubs(interp, "8.1", 0) == NULL) {
        return TCL_ERROR;
    }
 #endif

  Tcl_CreateObjCommand(interp,"LiveMsg",LiveMsgObjCmd,
   (ClientData)NULL, (Tcl_CmdDeleteProc *)NULL);


  code=Tcl_PkgProvide(interp,"LiveMsg","1.0");
  if (code != TCL_OK) {
   return code;
  }

  // init here
  return TCL_OK;
 }














Also see "How to write C-coded extensions for Tcl". and http://www.tcl.tk/doc/howto/stubs.html