You are here

C API 를 동적 라이브러리로 정의 후 TCL에서 호출 하는법

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)을 호출하기 위한 과정은 다음과 같다.

1. 헤더 정보에서 각 API들을 extern을 사용하여 외부에서 호출할 수 있도록 한다.
2. 각각의 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");
}

3. 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:
        <a href="mailto:-@del">-@del</a> /q $(OBJS)
        <a href="mailto:-@del">-@del</a> /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:
        <a href="mailto:-@del">-@del</a> /q $(OBJS)
        <a href="mailto:-@del">-@del</a> /q $(TARGET)

4. MS-DOS창에서 nmake -f makefile이름

MS-DOS창에서 해당 소스와 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

수고하셨습니다. ^^

위 방법을 전수해주신 admin님 진심으로 감사합니다. ^^

포럼: