앞의 강좌에서는 Tcl의 커맨드를 C언어에서 호출하는 방법에 대해서 알아보았습니다. 이번글에서는 역으로 C언어로 Tcl의 커맨드를 추가하여 Tcl에서 호출하는 방법에 대해서 알아보겠습니다. 앞서 말씀드렸듯이 exe를 만들지, 아니면 DLL을 만들지에 대해서 언급드렸지만, 커맨드를 추가하는 원시 프로그램은 공통입니다. 우선 아래의 소스를 보도록 하겠습니다.
// monthname.c
#include <stdio.h>
#include <tcl.h>
static int monthnameHandleProc(
ClientData data, Tcl_Interp* interp, int objc, Tcl_Obj* CONST objv[])
{
static char* months[] = {
"", "Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
};
long m;
if(objc != 2){
Tcl_WrongNumArgs(interp, 1, objv, "month(1..12)");
return TCL_ERROR;
}
if(Tcl_GetLongFromObj(interp, objv[1], & m) != TCL_OK || m < 1 || m > 12) {
Tcl_AppendToObj(Tcl_GetObjResult(interp), "Argument must be 1..12.", -1);
return TCL_ERROR;
}
Tcl_SetObjResult(interp, Tcl_NewStringObj(months[m], -1));
return TCL_OK;
}
DLLEXPORT int Monthname_Init(Tcl_Interp* interp) {
Tcl_InitStubs(interp, "8.1", 0);
Tcl_CreateObjCommand(interp, "monthname", monthnameHandleProc, NULL, NULL);
return Tcl_PkgProvide(interp, "monthname", "1.00");
}
위의 소스를 monthname.c로 작성을 합니다. 위의 소스는 monthname이라고 하는 Tcl 커맨드를 정의하고 있습니다.
set a [monthname 10]
이라고 한다면 "Oct" 가 변수 a에 세팅되는 커맨드입니다. 만약 monthname 2000이나 monthname abcd라고 한다면 "Argument must be 1...12" 라는 메시지를 띄울 것입니다. 위의 소스는 Tcl_...이라는 함수가 많이 쓰입니다. 자세한 설명이 필요하시면 매뉴얼을 찾아 보시면 될 것입니다. 마지막으로 컴파일을 하여 실행을 해봅니다.
Borland C++
bcc32 -tWD -IC:\tcl\include -LC:\tcl\lib monthname.c tcl84bcc.lib
Visual C++
cl -o monthname.dll /LD -I"C:\tcl\include" monthname.c "C:\tcl\lib\tcl84.lib"
실행을 시킨 화면은 아래와 같습니다.
참고
bcc32 컴파일러로 다음과 같은 에러가 나며 dll 파일이 만들어 지지 않는 이유는
C:\Temp>bcc32 -tWD -IC:\tcl\include -LC:\tcl\lib onthname.c c:\tcl\lib\tcl84bcc.lib
Borland C++ 5.5.1 for Win32 Copyright (c) 1993, 2000 Borland
monthname.c:
Warning W8057 monthname.c 25: Parameter 'data' is never used in function monthnameHandleProc
Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland
Error: Unresolved external '_Tcl_CreateObjCommand' referenced from C:\TEMP\MONTHNAME.OBJ
ActiveTcl 8.4.5 이상 버전을 사용하시는 분들일 것입니다. 최신의 ActiveTcl 8.4.5에 포함된 tcl84.dll이 이제 앞으로 borland 컴파일러를 지원하지 않는 것인지, 아니면 implib의 버그인지 알 수 없지만, 최신의 tcl84.dll으로 tcl84bcc.lib로의 변경이 안됩니다.
변경은 돼도 실제 컴파일 시 링크할때 위와 같이 에러가 나고 있습니다. 현재로서 해결책은 없지만, 8.4.5의 전 버전인 8.4.4로 borland용의 lib로 변경해서 컴파일시 이용하는 방법밖엔 없을 것 같습니다. 참고로 ActiveTcl 8.4.4에 포함되어 있는 tcl84.dll과 tk84.dll을 볼랜드용의 lib로 변환한 파일을 첨부합니다.