Tcl/Tk의 버전과 Stubs

admin의 아바타

공유 라이브러리(dll, so)로 Tcl/TK의 커맨드를 추가 하는 것은, Tcl/Tk 인터프리터에 손상을 주지않고 기존의 확장 tclsh나 확장 wish를 빌드하여 배포하는 방법보다도 편하기 때문에, 대부분의 유명한 확장 라이브러리는 공유 라이브러리 형태로 배포되고 있습니다. 사실 이것만으로도 충분하지만, Tcl/TK 8.1부터 지원되고 있는 Stub라고 하는 기능을 사용한다면, Tcl/TK의 각 버전에 있는 헤더파일과 라이브러리로 빌드하여 만들어진 공유 라이브러리를 다른 버전의 Tcl/Tk 에 로드 하여 사용할수 있게 됩니다.

#include <stdlib.h>
#include <string.h>
#include <tcl.h>
 
static int maxObjCmd(
   ClientData clientData, Tcl_Interp* interp,
   int objc, Tcl_Obj* CONST objv[]){
   int  i;
   double maxvalue = 0;
 
   if(objc == 1){
      Tcl_WrongNumArgs(interp, 1, objv, "num num...");
      return TCL_ERROR;
   }
   for(i=1; i<objc; i++){
      double v;
      if(Tcl_GetDoubleFromObj(interp, objv[i], & v) == TCL_ERROR){
      return TCL_ERROR;
      }
      if(i == 1 || v > maxvalue) maxvalue = v;
   }
   Tcl_SetObjResult(interp, Tcl_NewDoubleObj(maxvalue));
   return TCL_OK;
}
 
DLLEXPORT int Max_Init(Tcl_Interp* interp){
#ifdef USE_TCL_STUBS
   Tcl_InitStubs(interp, "8.1", 0);
#endif
   Tcl_CreateObjCommand(interp, "max", maxObjCmd, NULL, NULL);
   return Tcl_PkgProvide(interp, "max", "1.00");
}

전 강좌의 소스와 비교했을때 다른곳은 어디일까요?바로 초기화 부분에 3행이 추가됐습니다.

#ifdef USE_TCL_STUBS
   Tcl_InitStubs(interp, "8.1", 0);
#endif

Stub 기능을 사용하는데 필요한 처리는 이것 뿐 입니다. Tcl_InitStubs는 반드시 초기화 함수의 선두 부분에 써야 합니다.

두번째 인자에는

Tcl_InitStubs(interp, "8.1", 0);

지원 가능한 Tcl의 최저 버전을 문자열로 지정합니다. 3번째 인자는, 2번째 인자에 적은 버전보다 높은 버전 이라면 어느 버전도 로드할수 있다의 의미인 0을 적고, 아니면 2번째 인자에 기록한 버전만 로드할수 있는 1을 적습니다. 보통은 0으로 적는게 좋습니다. 또한, Tcl뿐만 아니라 TK의 API를 사용할 경우에도 Tk_InitStubs를 사용할수 있습니다.

#ifdef USE_TCL_STUBS
   Tcl_InitStubs(interp, "8.1", 0);
#endif
#ifdef USE_TK_STUBS
   Tk_InitStubs(interp, "8.1", 0);
#endif

VC++의 nmake 파일은 다음과 같습니다.

CC = cl
SHLD = cl /LD
TCLROOT = C:\TCL
CFLAGS =/nologo /O2 /I"$(TCLROOT)\include" /DWIN32 /DUSE_TCL_STUBS
LDFLAGS =/nologo
LIBS ="$(TCLROOT)\lib\tclstub84.lib" \ 
      "$(TCLROOT)\lib\tkstub84.lib" \ 
      "$(TCLROOT)\lib\tcl84.lib" \ 
      "$(TCLROOT)\lib\tk84.lib"
.c.obj:
   $(CC)$(CFLAGS) -c $*.c
OBJS = max.obj
max.dll:$(OBJS)
   $(SHLD) /o $@ $(LDFLAGS) $(OBJS) $(LIBS)

앞서 나왔던 Makefile 하고는 다릅니다. 컴파일 옵션에 /DUSE_TCL_STUBS 가 추가 된 것과, 링크한 라이브러리가 tcl84.lib와 tk84.lib 뿐만 아니라, tclstub84.lib와 tkstub84.lib가 추가 되었습니다. Tk의 API를 사용할경우 /DUSE_TK_STUBS도 함께 붙일 필요가 있습니다. 이제 max.dll을 wish83에 로드하여 보고, wish84에 로드하여 보면 이상 없이 불러와 지는걸 보실수 있을겁니다. 이것으로 사용자들은 여러분이 만든 공유 라이브러리를 어느 버전에서도 사용할수 있게됩니다.

첨부 파일파일 크기
55.jpg34.81 KB