pcm0279 님이 올려주신 팁입니다.
C 프로그램에서 정의한 API들을 동적 라이브러리(.dll)로 만들어 Tcl script에서 C API 명령을 호출하여 사용하는 방법이다. 다음은 C프로그램의 예제소스이다.
// calc.h
extern int sum(int a, int b); // extern을 사용하여 외부에서 호출 가능하도록 함.
extern int minus (int c, int d); // extern을 사용하여 외부에서 호출 가능하도록 함.
// calc.c
#include <stdio.h>
#include "calc.h"
int sum(int a, int b) {
return a+b;
}
int minus (int c, int d) {
return c-d;
}
위 API들(sum,minus)을 호출하기 위한 과정은 다음과 같다.
- 헤더 정보에서 각 API들을 extern을 사용하여 외부에서 호출할 수 있도록 한다.
- 각각의 API들을 패키지로 만든다.
// tclsum.c
#include <tcl.h>
#include "calc.h"
static int sum_HandleProc( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
int a, b, c;
Tcl_GetInt(interp, Tcl_GetString(objv[1]), &a);
Tcl_GetInt(interp, Tcl_GetString(objv[2]), &b);
c = sum(a, b); // <-- sum API 호출 부분
Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
return TCL_OK;
}
DLLEXPORT int Sum_Init(Tcl_Interp* interp){
Tcl_CreateObjCommand(interp, "sum", sum_HandleProc, NULL, NULL);
return Tcl_PkgProvide(interp, "sum", "1.00");
}
// tclminus.c
#include <tcl.h>
#include "calc.h"
static int minus_HandleProc( ClientData data, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])
{
int a, b, c;
Tcl_GetInt(interp, Tcl_GetString(objv[1]), &a);
Tcl_GetInt(interp, Tcl_GetString(objv[2]), &b);
c = minus(a, b); // <-- minus API 호출 부분
Tcl_SetObjResult(interp, Tcl_NewIntObj(c));
return TCL_OK;
}
DLLEXPORT int Minus_Init(Tcl_Interp* interp){
Tcl_CreateObjCommand(interp, "minus", minus_HandleProc, NULL, NULL);
return Tcl_PkgProvide(interp, "minus", "1.00");
}
makefile 작성
# makefile_sum
TCL = c:\tcl # tcl 위치
SHLD = cl /LD
CFLAGS = /nologo /O2 /I"$(TCL)\include"
LDFLAGS = /nologo
LIBS = "$(TCL)\lib\tcl85.lib" "$(TCL)\lib\tk85.lib" # $(TCL)\lib\tcl<tcl version No.>.lib
TARGET = sum.dll # 동적 라이브러리 지정
SRC = calc.c tclsum.c # 소스파일 지정
OBJS = $(SRC:.c=.obj)
.SUFFIXES:
.SUFFIXES: .c .obj
.c.obj:
$(CC) /c $(CFLAGS) /Fo$*.obj $<
$(TARGET): $(OBJS)
$(SHLD) /o $@ $(LDFLAGS) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
del /q $(OBJS)
del /q $(TARGET)
# makefile_minus
TCL = c:\tcl # tcl 위치
SHLD = cl /LD
CFLAGS = /nologo /O2 /I"$(TCL)\include"
LDFLAGS = /nologo
LIBS = "$(TCL)\lib\tcl85.lib" "$(TCL)\lib\tk85.lib" # $(TCL)\lib\tcl<tcl version No.>.lib
TARGET = minus.dll # 동적라이브러리 지정
SRC = calc.c tclminus.c # 소스파일 지정
OBJS = $(SRC:.c=.obj)
.SUFFIXES:
.SUFFIXES: .c .obj
.c.obj:
$(CC) /c $(CFLAGS) /Fo$*.obj $<
$(TARGET): $(OBJS)
$(SHLD) /o $@ $(LDFLAGS) $(OBJS) $(LIBS)
all: $(TARGET)
clean:
del /q $(OBJS)
del /q $(TARGET)
cmd 창에서 해당 소스와 makefile위치로 이동 후
> nmake -f makefile_sum
.....................
.....................
Creating library sum.lib and object sum.exp
> nmake -f makefile_minus
.....................
.....................
Creating library minus.lib and object minus.exp
위와 같은 메시지가 나타났다면 검증을 해보겠다. 폴더안에 .dll, .exp, .lib, .obj파일이 생성되었는지 확인한다. cmd.exe 를 실행한다.
>tclsh85
%load sum.dll
%sum 3 6
9
%load minus.dll
%minus 5 3
2
위 과정이 모두 정상적으로 진행이 되었다면 C API호출법은 끝난 것이다. 마지막으로 .tcl파일을 작성하여 정상적으로 호출되는지 테스트를 해보겠다.
# test.tcl
load sum.dll
load minus.dll
puts [sum 10 1]
puts [minus 10 1]
gets stdin
cms를 실행 후
>tclsh85 test.tcl
11
9
수고하셨습니다. ^^ 위 방법을 전수해 주신 운영자님 진심으로 감사합니다. ^^
'Tcl & Tk > 팁 (Tip)' 카테고리의 다른 글
에러없는 변수 접근법 (0) | 2025.03.17 |
---|---|
자신의 IP 알아내기 (0) | 2025.03.17 |
클립보드 사용하기 (0) | 2025.03.17 |
Tcl/Tk 소스를 숨기고 독립적인 실행파일을 만드는 가장 간단한 방법 (0) | 2025.03.14 |
subst 커맨드: 특정값을 가진 변수이름을 다른 변수에 넣어 사용하기 (0) | 2025.03.14 |