본 장은 API 사용 프로그램 예제를 설명한다.
다음과 같은 함수를 동적 모듈로 컴파일하여 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;
}
이 모듈을 사용하는 측에서는 다음과 같이 사용한다.
/* 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);
}
본 절에서는 C++에서 TDL을 사용하는 인터페이스를 설명한다.
다음과 같은 함수를 동적 모듈로 컴파일하여 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; }
이 모듈을 사용하는 측에서는 다음과 같이 사용한다.
#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;
}
클래스는 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
#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);
}
본 절에서는 TDL 환경설정 중 기존의 MAXMODULES 변경 기능과 tdlsync와 tdlinit을 이용한 MAXMODULES 변경에 대해 설명한다.
다음은 기존의 MAXMODULES 변경하는 방법이다. 모듈의 재배치가 필요하기 때문에 많은 시간이 소요되는 단점이 있다.
> tdlrm > tdlinit
tdlsync와 tdlinit을 이용한 MAXMODULES 변경 방법은 다음과 같다.
변경된 MAXMODULES 값을 기반으로 새로운 인덱스만 계산하여 초기화한다. 모듈의 재배치 과정이 없기 때문에, “4.4.1. 기존의 MAXMODULES 변경”의 방식보다 시간과 비용이 절감된다.
> tdlsync -B original_maxmodules.bak - tdl.cfg 의 MAXMODULES 값을 변경 > tdlinit -B original_maxmodules.bak