예제

본 장은 API 사용 프로그램 예제를 설명한다.

1. 기본적인 사용 예

  1. 다음과 같은 함수를 동적 모듈로 컴파일하여 my_function.sl을 생성한다.

    #include <tdlcall.h>
    
    /* tdlcall로 호출되어질 함수 */
    long my_function(void *args)
    {
         long urcode;
    
         urcode = (long)time (NULL);
         strcpy((char*)args, "my_function");
         return urcode;
    }
  2. 이 모듈을 사용하는 측에서는 다음과 같이 사용한다.

    /* TDL 관련 함수들을 사용하기 위하여 반드시 include 필요 */
    #include <tdlcall.h>
    
    int retval;
    char data[256];
    long urcode;
    
    /* tdlcall 함수 호출 : TDL Version 1 */
    retval = tdlcall("my_function", (void*)data, &urcode, TDL_NOFLAGS);
    if (retval != TDL_OK) {
          printf("tdlcall(%s) = %d, with err[%s]\n", "my_function", retval, tdlerror(retval));
    } else {
           /* my_function 함수에서 전달받은 값 출력 */
           printf("tdlcall(%s) = %d, urcode = %#08x, data = %s\n","my_function", retval, urcode, data);
    }

2. C++ 인터페이스 사용 예

본 절에서는 C++에서 TDL을 사용하는 인터페이스를 설명한다.

  1. 다음과 같은 함수를 동적 모듈로 컴파일하여 dlib.so를 생성한다.

    • dlib.h

      /* dlib.h */
      
      namespace TmaxSoft {
              class Airplain {
                      private:
                              int state;
                      public:
                              Airplain();
                              virtual char *Start();
                              virtual char *Stop();
                              virtual int getState();
              };
      }
      
      class Car {
              private:
                      int state;
              public:
                      Car();
                      virtual char *Start();
                      virtual char *Stop();
                      virtual int getState();
      };
    • dlib.cpp

      /* dlib.cpp */
      
      #include <string.h>
      #include <usrinc/tdlcall.h>
      #include "dlib.h"
      
      long tdlcreate_cb(const char *snm, const char *cnm, void *args, void **obj) {
              if (0) {
              } else if (!strcmp(snm, "TmaxSoft") && !strcmp(cnm, "Airplain")) {
                      *obj = (void *) new TmaxSoft::Airplain();
                      if (*obj != NULL) return 1;
                      else return -1;
              } else if (!strcmp(snm, "") && !strcmp(cnm, "Car")) {
                      *obj = (void *) new Car();
                      if (*obj != NULL) return 1;
                      else return -1;
              }
              return -1;
      }
      
      long tdldestroy_cb(const char *snm, const char *cnm, void *args, void *obj) {
              if (0) {
              } else if (!strcmp(snm, "TmaxSoft") && !strcmp(cnm, "Airplain")) {
                      delete (TmaxSoft::Airplain *)obj;
                      return 1;
              } else if (!strcmp(snm, "") && !strcmp(cnm, "Car")) {
                      delete (Car *)obj;
                      return 1;
              }
              return -1;
      }
      
      TmaxSoft::Airplain::Airplain() { state = 0; }
      char* TmaxSoft::Airplain::Start() {
      state = 2; return (char *)"TmaxSoft::Airplain::Start "; }
      char* TmaxSoft::Airplain::Stop() {
      state = 1; return (char *)"TmaxSoft::Airplain::Stop "; }
      int TmaxSoft::Airplain::getState() { return state; }
      
      Car::Car() { state = 0; }
      char* Car::Start() { state = 2; return (char *)"Car::Start "; }
      char* Car::Stop() { state = 1; return (char *)"Car::Stop "; }
      int Car::getState() { return state; }
  2. 이 모듈을 사용하는 측에서는 다음과 같이 사용한다.

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <usrinc/tdlcall.h>
    #include "dlib.h"
    
    int
    main(int argc, char *argv[])
    {
            int ret;
            long urcode;
            TmaxSoft::Airplain *obj;
    
            if ((ret = tdlcreate("dlib", "TmaxSoft", "Airplain", NULL, (void **)&obj,
                                  &urcode, 0)) < 0)
            {
                    printf("obj is NULL\n");
                    printf("%s\n", tdlerror(ret));
            } else {
                    printf("obj %s\n", obj->Start());
                    printf("obj %s\n", obj->Stop());
                    printf("obj %d\n", obj->getState());
            }
    
            return 0;
    }
  3. 클래스는 nm에서 심볼을 정확하게 확인하기 어렵기 때문에 tdlinit, tdlupdate의 경우에는 반드시 exp 파일이 필요하다. export 파일의 사용 방법은 다음과 같다.

    VERSION=1, 2, 3으로 설정된 경우에는 함수명을 한 줄에 하나씩 나열했지만, VERSION=4로 설정한 경우에는 클래스명을 한 줄에 하나씩 나열한다. 만약 네임스페이스가 적용된 경우에는 namespace::classname 형태로 한 줄에 하나씩 나열한다.

    # libuser.so
    foo
    bar
    
    # libuserclass.so
    classCar
    classBus
    tmaxsoft::classCar
    tmaxsoft::classBus
    tibero::myClass

3. 명시적 버전 보호 사용 예

#include <stdio.h>
#include <stdlib.h>
#include <usrinc/atmi.h>
#include <usrinc/tmaxapi.h>
#include <usrinc/tdlcall.h>

TSVC1(TPSVCINFO *msg)
{
    int i;
    int n;
    long urcode;
    char *rcvbuf;
    long rcvlen;
    int ret;

    printf("TSVC1 service is started!\n");

    /* tdlstart 호출하여 명시적 버전 보호 시작 */
    tdlstart();
    n = tdlcall("myfunction1", (void*)msg->data, &urcode, 0);
    if (n != TDL_OK) {
         printf("tdlcall(myfunction1) = %d, with err[%s]\n", n, tdlerror(n));
    } else {
         printf("tdlcall(myfunction1) = %d, urcode = %#08x\n", n, urcode);
    }
    sprintf((char *)msg->data, "[TSVC1]tdlcall(myfunction1)=%d", urcode);
    if ((rcvbuf = (char *)tpalloc("STRING", NULL, 0)) == NULL) {
         printf("recvbuf alloc failed !\n");
         tpreturn (TPFAIL, -1, NULL, 0, 0);
    }

    if(tpcall("TSVC2", rcvbuf, 0, &rcvbuf, &rcvlen, 0)==-1) {
        printf("Can't send request to service TSVC2[%d]\n", tperrno);
        tpfree((char *)rcvbuf);
        tpreturn (TPFAIL, -1, NULL, 0, 0);
    }

    /* tdlend 호출하여 명시적 버전 보호 종료 */
    tdlend();
    strcat((char *)msg->data, rcvbuf);
    msg->len = strlen((char *)msg->data);
    tpreturn(TPSUCCESS,0,(char *)msg->data, msg->len, 0);
}

4. 추가 기능 예제

본 절에서는 TDL 환경설정 중 기존의 MAXMODULES 변경 기능과 tdlsync와 tdlinit을 이용한 MAXMODULES 변경에 대해 설명한다.

4.1. 기존의 MAXMODULES 변경

다음은 기존의 MAXMODULES 변경하는 방법이다. 모듈의 재배치가 필요하기 때문에 많은 시간이 소요되는 단점이 있다.

> tdlrm
> tdlinit

4.2. tdlsync와 tdlinit을 이용한 MAXMODULES 변경

tdlsync와 tdlinit을 이용한 MAXMODULES 변경 방법은 다음과 같다.

변경된 MAXMODULES 값을 기반으로 새로운 인덱스만 계산하여 초기화한다. 모듈의 재배치 과정이 없기 때문에, 기존의 MAXMODULES 변경의 방식보다 시간과 비용이 절감된다.

> tdlsync -B original_maxmodules.bak
- tdl.cfg 의 MAXMODULES 값을 변경
> tdlinit -B original_maxmodules.bak