Visual Basic 인터페이스
본 장은 Visual Basic 인터페이스에서 사용하는 함수와 예제를 설명한다.
1. 개요
Visual Basic 인터페이스에는 Power Builder와 달리 별도의 모듈이 존재하지 않으며 단순히 클라이언트 라이브러리를 호출할 수 있도록 함수의 프로토타입을 정의한 인터페이스 모듈이 존재한다.
Visual Basic 인터페이스 모듈은 다음과 같다.
모듈 | 설명 |
---|---|
atmi.bas |
atmi 함수에 대한 프로토타입 정의 파일이다. |
fdl. Bas |
필드키 함수에 대한 프로토타입 정의 파일이다. |
comm.bas |
사용자의 편리를 위한 매크로 정의 파일이다. |
winapi.bas |
Windows에서 제공하는 함수 정의 파일이다. |
개발자는 위의 인터페이스 모듈을 설치하면 Tmax 클라이언트 라이브러리에서 제공하는 함수를 호출하여 사용할 수 있다. 하지만 Visual Basic은 값 전달 방법이 기존의 다른 애플리케이션과 많이 다르기 때문에 이 점에 주의하여 사용해야 한다. 또한 직접적인 버퍼 조작이 어렵기 때문에 매크로(comm.bas)를 제공하여 데이터를 입력하고 꺼내는 작업을 내부적으로 처리해준다.
다음은 매크로에서 제공하는 함수의 목록이다.
함수 | 설명 |
---|---|
주어진 StrErr 메시지와 함께 fberrno를 화면에 MsgBox로 출력하는 함수이다. |
|
Tmax 시스템과 연결하기 위해 설정해야 하는 버퍼인 tpstart_t 구조체를 구성하는 함수이다. |
|
CARRAY 버퍼에 String 데이터 text를 입력하는 함수이다. |
|
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Image 데이터를 ByteArray에 저장하는 함수이다. |
|
Tmax FDL 함수인 fbchg_tu()를 이용하여 지정한 nth에 해당하는 순번으로 Field에 지정된 필드명에 value값을 가져오는 함수이다. |
|
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Double 데이터를 dData에 저장하는 함수이다. |
|
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Single 데이터를 dData에 저장하는 함수이다. |
|
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Integer 데이터를 iData에 저장하는 함수이다. |
|
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Long 데이터를 lData에 저장하는 함수이다. |
|
STRING 버퍼의 데이터를 text에 저장하는 함수이다. |
|
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 String 데이터를 text에 저장하는 함수이다. |
|
CARRAY 버퍼에 String 데이터 text를 입력하는 함수이다. |
|
FIELD 버퍼에 Image 데이터를 필드 순번으로 입력하는 함수이다. |
|
Tmax FDL 함수인 fbchg_tu()를 이용하여 지정한 nth에 해당하는 순번으로 fldName에 지정된 필드명에 value값을 저장하는 함수이다. |
|
FIELD 버퍼에 Double 데이터를 필드 순번으로 입력하는 함수이다. |
|
FIELD 버퍼에 Single 데이터를 필드 순번으로 입력하는 함수이다. |
|
FIELD 버퍼에 Integer 데이터를 필드 순번으로 입력하는 함수이다. |
|
FIELD 버퍼에 Long 데이터를 필드 순번으로 입력하는 함수이다. |
|
STRING 버퍼의 데이터를 text에 저장하는 함수이다. |
|
FIELD 버퍼에 String 데이터를 필드 순번으로 입력하는 함수이다. |
|
주어진 StrErr 메시지와 함께 tperrno에 해당하는 String 에러가 화면에 MsgBox로 출력되는 함수이다. |
atmi 함수와 필드키 함수에 대한 프로토타입 및 기능은 Tmax Reference Guide 및 Tmax Application Development Guide를 참고한다. |
2. 함수
2.1. FdlErrorMsg
주어진 StrErr 메시지와 함께 fberrno를 화면에 MsgBox로 출력하는 함수이다.
-
프로토타입
Sub FdlErrorMsg(StrErr As String)
-
파라미터
파라미터 설명 StrErr
에러 메시지이다.
-
반환값
메시지 윈도우를 출력한다.
-
예제
lret = fbput(ByVal lsendbuf, ByVal lfid, ByVal txtInput.text, ByVal 0) If lret = -1 Then FdlErrorMsg("fbput") error processing … End If
-
관련함수
TmaxError()
2.2. FilltpstartBuf
Tmax 시스템과 연결하기 위해 설정해야 하는 버퍼인 tpstart_t 구조체를 구성하는 함수이다.
-
프로토타입
Function FilltpstartBuf(sndbufp As Long, startinfop As tpstart_t) As Long
-
파라미터
파라미터 설명 sndbufp
tpalloc 함수로 메모리에 할당된 버퍼를 의미한다.
startinfop
tpstart_t형으로 선언된 변수를 의미한다.
-
예제
Dim lsndbuf As Integer Dim lret As Integer Dim cinfo As tpstart_t lsndbuf = tpalloc("TPSTART", "", 0) If lsndbuf = 0 Then error processing End If cinfo.cltname = "tmax" + Chr(0) cinfo.usrname = "tmax" + Chr(0) cinfo.dompwd = "xamt" + Chr(0) cinfo.usrpwd = "batman" + Chr(0) cinfo.flags = TPUNSOL_HND lret = FilltpstartBuf(lsndbuf, cinfo) If ret < 0 Then error processing End If ret = tpstart(lsndbuf) If ret < 0 Then error processing End If …
-
관련함수
TmaxError()
2.3. GETCAR
CARRAY 버퍼에 String 데이터 text를 입력하는 함수이다.
-
프로토타입
Function GETCAR(ByVal Carptr&, text As String, Datalen As Long) As Long
-
파라미터
파라미터 설명 Carptr
FDL 버퍼의 포인터이다.
text
데이터를 의미한다.
Datalen
데이터 길이이다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lrecvbuf As Long Dim text As String Dim lret As Long Dim lrbuflen As Long … lsendbuf = tpalloc("CARRAY", "", 1024) lrecvbuf = tpalloc("CARRAY", "", 1024) … lret = tpcall(ByVal "SVC1", ByVal lsendbuf, ByVal DataLen&, lrecvbuf, lrbuflen, ByVal 0) … 'CARRAY 버퍼에서는 반드시 데이터의 길이값을 입력해야 한다. lret = GETCAR(lsendbuf, text, lrbuflen) …
-
관련함수
GETINT(), GETLONG(), GETDOUBLE(), GETVAR(), GETSTR(), GETFLOAT(), GETSTR(), GETCHR()
2.4. GETCAR_BA
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Image 데이터를 ByteArray에 저장하는 함수이다.
-
프로토타입
Function GETCAR_BA (ByVal Fdlptr&, Field As String, idx As Long, ByRef ByteArray() As Byte, datalen As Long) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
ByteArray
데이터를 의미한다.
datalen
ByteArray의 길이이다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim rbuffer(102400) As Byte Dim datalen As Long … lrecvbuf = tpalloc("FIELD", "", 102400) … lret = PUTCAR_BA(ByVal lsendbuf, "TP_BITMAP", 0, lbuffer, datalen) if lret < 0 then error processing … end if … lret = tpcall(ByVal "FILEUP", ByVal lsendbuf, ByVal datalen&, lrecvbuf, lrbuflen, ByVal 0) lblComment.Caption = lblComment.Caption & " -> tpcall : " & lret If lret = -1 Then error processing … end If … lret = GETCAR_BA(ByVal lrecvbuf, "TP_BITMAP", 0, rbuffer, datalen) if lret < 0 then error processing … end if …
-
관련함수
GETINT(), GETLONG(), GETDOUBLE(), GETCAR(), GETVAR(), GETFLOAT(), GETSTR(), GETCHR()
2.5. GETCHR
Tmax FDL 함수인 fbchg_tu()를 이용하여 지정한 nth에 해당하는 순번으로 Field에 지정된 필드명의 value값을 가져오는 함수이다. 이때 value값은 Char가 된다. fbget_tu()를 사용하므로 필드 순번(idx)의 데이터(char)를 가져온다.
-
프로토타입
Function GETCHR(ByVal Fdlptr&, ByVal Field As String, ByVal idx As Integer, ByRef data As String, ByVal datalen As Integer) As Integer
-
파라미터
파라미터 설명 Fldptr
STRING 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
data
저장할 string 데이터이다.
datalen
저장할 string 데이터의 길이이다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim chr As String lsendbuf = fballoc(10, 100) Irecvbuf = fballoc(10, 100) … lret = tpcall(ByVal "SVC1", ByVal lsendbuf, ByVal DataLen&, lrecvbuf, lrbuflen, ByVal 0) … lret = GETSTR(lrecvbuf, "CHR", 0, chr, 1 ) …
-
관련함수
GETINT(), GETLONG(), GETDOUBLE(), GETVAR(), GETSTR(), GETCAR(), GETFLOAT()
2.6. GETDOUBLE
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Double 데이터를 dData에 저장하는 함수이다.
-
프로토타입
Function GETDOUBLE(ByVal Fdlptr&, Field As String, idx As Long, dData As Double) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
dData
데이터를 의미한다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim doubledata As Double lsendbuf = tpalloc("FIELD ", "", 0) … lret = GETDOUBLE(ByVal lsendbuf, "DOUBLEDATA", 0, doubledata) …
-
관련함수
GETINT(), GETLONG(), GETVAR(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()
2.7. GETFLOAT
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Single 데이터를 dData에 저장하는 함수이다.
-
프로토타입
Function GETFLOAT (ByVal Fdlptr&, Field As String, idx As Long, dData As Single) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
dData
데이터를 의미한다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim doubledata As Single lsendbuf = tpalloc("FIELD ", "", 0) … lret = GETFLOAT (ByVal lsendbuf, "DOUBLEDATA", 0, doubledata) …
-
관련함수
GETINT(), GETLONG(), GETVAR(), GETCAR(), GETSTR(), GETCHR(), GETDOUBLE()
2.8. GETINT
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Integer 데이터를 iData에 저장하는 함수이다.
-
프로토타입
Function GETINT(ByVal Fdlptr&, Field As String, idx As Long, iData As Integer) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
iData
데이터를 의미한다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim intdata As Integer lsendbuf = tpalloc("FIELD ", "", 0) lret = GETINT(ByVal lsendbuf, "INTDATA", 0, intdata) …
-
관련함수
GETLONG(), GETDOUBLE(), GETVAR(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()
2.9. GETLONG
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 Long 데이터를 lData에 저장하는 함수이다.
-
프로토타입
Function GETLONG(ByVal Fdlptr&, Field As String, idx As Long, lData As Long) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
lData
데이터를 의미한다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim longdata As Long lsendbuf = tpalloc("FIELD ", "", 0) … lret = GETLONG(ByVal lsendbuf, "LONGDATA", 0, longdata) …
-
관련함수
GETINT(), GETDOUBLE(), GETVAR(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()
2.10. GETSTR
STRING 버퍼의 데이터를 text에 저장하는 함수이다.
-
프로토타입
Function GETSTR(ByVal strptr&, text As String) As Long
-
파라미터
파라미터 설명 strptr
STRING 버퍼의 포인터이다.
text
데이터를 의미한다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim text As String lsendbuf = fballoc(10, 100) Irecvbuf = fballoc(10, 100) … lret = tpcall(ByVal "SVC1", ByVal lsendbuf, ByVal DataLen&, lrecvbuf, lrbuflen, ByVal 0) … lret = GETSTR(lrecvbuf, text) …
-
관련함수
GETINT(), GETLONG(), GETDOUBLE(), GETVAR(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()
2.11. GETVAR
FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 입력된 필드 순번 idx의 String 데이터를 text에 저장하는 함수이다.
-
프로토타입
Function GETVAR(ByVal Fdlptr&, Field As String, idx As Long, text As String) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
text
데이터를 의미한다.
-
반환값
반환값 설명 1
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long lsendbuf = tpalloc("FIELD ", "", 0) … lret = GETVAR(ByVal lsendbuf, "INPUT", 0, txtOutput.text) …
-
관련함수
GETINT(), GETLONG(), GETDOUBLE(), GETCAR(), GETFLOAT(), GETSTR(), GETCHR()
2.12. PUTCAR
CARRAY 버퍼에 String 데이터 text를 입력하는 함수이다.
-
프로토타입
Function PUTCAR(ByVal Carptr&, text As String, Datalen As Long) As Long
-
파라미터
파라미터 설명 Carptr
FDL 버퍼의 포인터이다.
text
데이터이다.
Datalen
데이터의 길이이다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lret As Long Dim DataLen As Long lsendbuf = tpalloc("CARRAY", "", 1024) 'CARRAY 버퍼에서는 반드시 데이터의 길이값을 입력해야 한다. DataLen = LenB(txtInput.text) lret = PUTCAR(ByVal lsendbuf, txtInput.text, DataLen) …
STRING 버퍼는 시스템에서 제공하는 lstrcpy 함수를 사용하여 데이터를 버퍼에 실을 수 있다.
Dim lsendbuf As Long Dim lret As Long lsendbuf = tpalloc("STRING", "", 1024) lret = lstrcpy(ByVal lsendbuf, ByVal txtInput.text)
-
관련함수
PUTINT(), PUTLONG(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR()
2.13. PUTCAR_BA
FIELD 버퍼에 Image 데이터를 필드 순번으로 입력하는 함수이다. FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 Image 데이터 ByteArray를 필드 순번 idx로 입력한다.
-
프로토타입
Function PUTCAR_BA(ByVal Fdlptr&, Field As String, idx As Long, ByteArray() As Byte, datalen As Long) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
ByteArray
데이터를 의미한다.
datalen
ByteArray의 길이를 의미한다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim iSrc As Integer Dim lCopy As Long Dim lSize As Long Dim lbuffer() As Byte Dim datalen As Long … lsendbuf = tpalloc("FIELD", "", 102400) … iSrc = FreeFile Open ".\nmlogo.bmp" For Binary Access Read As iSrc lSize = LOF(iSrc) datalen = lSize Do If lSize > MAX_BUFFER Then lSize = lSize - MAX_BUFFER lCopy = MAX_BUFFER Else lCopy = lSize End If ReDim lbuffer(lCopy - 1) Get iSrc, , lbuffer Loop Until lCopy = lSize Close iSrc lret = PUTCAR_BA(ByVal lsendbuf, "TP_BITMAP", 0, lbuffer, datalen) if lret < 0 then error processing … end if …
-
관련함수
PUTINT(), PUTLONG(), PUTDOUBLE(), PUTCAR(), PUTVAR(), PUTFLOAT(), PUTSTR(), PUTCHR()
2.14. PUTCHR
Tmax FDL 함수인 fbchg_tu()를 이용하여 지정한 nth에 해당하는 순번으로 fldName에 지정된 필드명에 value값을 저장하는 함수이다. 이때 value값은 Char가 된다. Fbchg_tu()를 사용하므로 필드 순번(nth)에 기존의 데이터가 있을 경우 주어진 데이터(value)로 변경이 되고, 필드 순번에 기존의 데이터가 없을 경우 주어진 데이터가 자동적으로 필드에 추가된다.
-
프로토타입
Function PUTCHR(ByVal Fdlptr&, ByVal Field As String, ByVal idx As Integer, ByRef data As String, ByVal datalen As Integer) As Integer
-
파라미터
파라미터 설명 Fldptr
STRING 버퍼의 포인터이다.
Fieldt
필드명을 의미한다.
idx
필드 순번을 의미한다.
data
저장할 string 데이터이다.
datalen
저장할 string 데이터의 길이이다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim chr As String lsendbuf = fballoc(10, 100) chr = "a" … lret = PUTSTR(lsendbuf, "CHR", 0, chr, 1 ) … Function PUTCHR(ByVal Fdlptr&, ByVal Field As String, ByVal idx As Integer, ByRef data As Char, ByVal datalen As Integer)
-
관련함수
PUTINT(), PUTLONG(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR()
2.15. PUTDOUBLE
FIELD 버퍼에 Double 데이터를 필드 순번으로 입력하는 함수이다. FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 Double 데이터 dData를 필드 순번 idx로 입력한다.
-
프로토타입
Function PUTDOUBLE(ByVal Fdlptr&, Field As String, idx As Long, dData As Double) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
dData
데이터를 의미한다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim doubledata As Double lsendbuf = tpalloc("FIELD ", "", 0) … lret = PUTDOUBLE(ByVal lsendbuf, "DOUBLEDATA", 0, doubledata) …
-
관련함수
PUTINT(), PUTLONG(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR(), PUTCHR()
2.16. PUTFLOAT
FIELD 버퍼에 Single 데이터를 필드 순번으로 입력하는 함수이다. FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 Single 데이터 dData를 필드 순번 idx로 입력한다.
-
프로토타입
Function PUTFLOAT(ByVal Fdlptr&, Field As String, idx As Long, dData As Single) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
dData
데이터를 의미한다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim doubledata As Single lsendbuf = tpalloc("FIELD ", "", 0) … lret = PUTFLOAT(ByVal lsendbuf, "DOUBLEDATA", 0, doubledata) …
-
관련함수
PUTINT(), PUTLONG(), PUTVAR(), PUTCAR(), PUTDOUBLE(), PUTSTR(), PUTCHR()
2.17. PUTINT
FIELD 버퍼에 Integer 데이터를 필드 순번으로 입력하는 함수이다. FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 Integer 데이터 iData를 필드 순번 idx로 입력한다.
-
프로토타입
Function PUTINT(ByVal Fdlptr&, Field As String, idx As Long, iData As Integer) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
iData
데이터를 의미한다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim intdata As Integer lsendbuf = tpalloc("FIELD ", "", 0) … lret = PUTINT(ByVal lsendbuf, "INTDATA", 0, intdata) …
-
관련함수
PUTLONG(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR(), PUTCHR()
2.18. PUTLONG
FIELD 버퍼에 Long 데이터를 필드 순번으로 입력하는 함수이다. FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 Long 데이터 lData를 필드 순번 idx로 입력한다.
-
프로토타입
Function PUTLONG(ByVal Fdlptr&, Field As String, idx As Long, lData As Long) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
lData
데이터를 의미한다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim longdata As Long lsendbuf = tpalloc("FIELD ", "", 0) … lret = PUTLONG(ByVal lsendbuf, "LONGDATA", 0, longdata) …
-
관련함수
PUTINT(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTSTR(), PUTCHR()
2.19. PUTSTR
STRING 버퍼의 데이터를 text에 저장하는 함수이다.
-
프로토타입
Function PUTSTR(ByVal strptr&, text As String) As Long
-
파라미터
파라미터 설명 strptr
STRING 버퍼의 포인터이다.
text
데이터를 의미한다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long Dim text As String lsendbuf = tpalloc("STRING", "", 1024) … lret = PUTSTR(lsendbuf, text) …
-
관련함수
PUTINT(), PUTLONG(), PUTDOUBLE(), PUTVAR(), PUTCAR(), PUTFLOAT(), PUTCHR()
2.20. PUTVAR
FIELD 버퍼에 String 데이터를 필드 순번으로 입력하는 함수이다. FIELD(FDL) 버퍼에 Field에 지정된 필드명으로 String, 데이터 text를 필드 순번 idx로 입력한다.
-
프로토타입
Function PUTVAR(ByVal Fdlptr&, Field As String, idx As Long, text As String) As Long
-
파라미터
파라미터 설명 Fdlptr
FDL 버퍼의 포인터이다.
Field
필드명을 의미한다.
idx
필드 순번을 의미한다.
text
데이터를 의미한다.
-
반환값
반환값 설명 -1 이외의 값
함수 호출에 성공한 경우이다.
-1
함수 호출에 실패한 경우이다.
-
예제
Dim lsendbuf As Long Dim lret As Long lsendbuf = tpalloc("FIELD ", "", 0) … lret = PUTVAR(ByVal lsendbuf, "INPUT", 0, txtInput.text) …
-
관련함수
PUTINT(), PUTLONG(), PUTDOUBLE(), PUTCAR(), PUTFLOAT(), PUTSTR(), PUTCHR()
2.21. TmaxError
주어진 StrErr 메시지와 함께 tperrno에 해당하는 string 에러가 화면에 MsgBox로 출력되는 함수이다.
-
프로토타입
Sub TmaxError(StrErr As String)
-
파라미터
파라미터 설명 StrErr
에러 메시지이다.
-
반환값
메시지 윈도우를 출력한다.
-
예제
Dim lsendbuf As Long Dim lrecvbuf As Long Dim lret As Long Dim lrbuflen As Long lsendbuf = tpalloc("CARRAY", "", 1024) lrecvbuf = tpalloc("CARRAY", "", 1024) lret = tpcall(ByVal "SVC1", ByVal lsendbuf, ByVal 0, lrecvbuf, lrbuflen, ByVal 0) If lret = -1 Then TmaxError ("tpcall (SVC1)") End If
-
관련함수
FdlErrorMsg()
3. 예제 프로그램
클라이언트 프로그램은 사용자의 요구를 받아서 서비스를 요청하고, 서버는 클라이언트에서 요구한 대로 Oracle 데이터베이스의 사원정보(EMP) 테이블에서 데이터를 입력, 수정, 조회 및 삭제한다.
3.1. 프로그램 구성
서버와 클라이언트 모두 환경설정이 되어 있어야 한다. TMAXDIR이나 포트 번호, 서버 IP 등의 환경설정이 이미 완료되어 있다고 가정하고 설정에 대한 내용은 생략한다.
다음의 예제 파일을 프로젝트에서 모듈로 추가한다.
-
<atmi.bas>
-
<fdl.bas>
-
<comm.bas>
-
<winapi.bas>
각각의 프로그램은 다음과 같은 파일들로 구성되어 있다.
-
공통 프로그램
프로그램 파일 설명 demo.f
필드키 버퍼를 정의한 파일이다.
tmax
라이브러리 파일이다.
tmconfig.m
Tmax 환경설정 파일이다.
-
클라이언트 프로그램
프로그램 파일 설명 EmployeeGrid.frm
조회 결과를 보여주는 프로그램이다.
EmployeeGrid.frx
조회 결과를 보여주는 프로그램이다.
EmployeeMgr.frm
Main 프로그램이다. 조회, 수정, 삭제 및 입력 기능을 수행한다.
MSSCCPRJ.SCC
Source Code Control 파일이다.
QA_4GL.vbg
클라이언트 프로그램 그룹 프로젝트 파일이다.
QA_4GL_Sample.exe
클라이언트 프로그램 실행 파일이다.
QA_4GL_Sample.vbp
클라이언트 프로그램 프로젝트 파일이다.
QA_4GL_Sample.vbw
클라이언트 프로그램 workspace 파일이다.
Atmi.bas
atmi 함수에 대한 프로토타입을 정의하는 파일이다.
comm.bas
사용자의 편의를 위한 매크로 정의 파일이다.
fdl.bas
필드키 함수에 대한 프로토타입을 정의하는 파일이다.
winapi.bas
Windows에서 제공하는 함수 정의 파일이다.
-
서버 프로그램
프로그램 파일 설명 emp_c.mk
Makefile이다.
emp_c.pc
서비스를 하는 서버 프로그램이다. AIX와 Oracle 9i를 사용했다.
3.2. 프로그램 특징
다음은 각 프로그램의 특징이다.
-
클라이언트 프로그램
기능 설명 Tmax 연결
NULL 인자로 연결한다.
버퍼 유형
FIELD KEY 버퍼, 구조체 파일을 fdlc 유틸리티로 컴파일하여 'fdl' 파일의 생성이 필요하다.
통신 유형
tpcall()을 이용한 동기 통신을 보내는 버퍼와 받는 버퍼를 다르게 지정한다.
트랜잭션 여부
TMS에서 AutoTransaction 부여한다.
-
서버 프로그램
기능 설명 서비스
FDLSELECT, FDLINSERT, FDLDELETE, FDLUPDATE를 작성한다.
데이터베이스 지정
Oracle 데이터베이스를 사용한다. 시스템 구성 파일의 SVRGROUP에 데이터베이스 정보를 지정한다.
통신 유형
tpcall()을 이용한 동기 통신을 보내는 버퍼와 받는 버퍼를 다르게 지정한다.
트랜잭션 여부
TMS에서 AutoTransaction 부여한다.
3.3. 공통 프로그램
DataBase EMP Table
다음은 Tmax EMP 데이터베이스(Oracle) 테이블의 예제이다.
EMPNO NUMBER NOT NULL P1 ENAME VARCHAR(16) JOB VARCHAR(16) MGR NUMBER HIREDATE DATE SAL NUMBER(7,2) COMM NUMBER(7,2) DEPTNO NUMBER
Tmax EMP 필드 테이블
다음은 Tmax EMP 필드 테이블의 예제이다.
<demo.f>
#For tmax demo employee program EMPNO 7500 long - - ENAME 7501 string - - JOB 7502 string - - MGR 7503 long - - DATE 7504 string - - SAL 7505 float - - COMM 7506 float - - DEPTNO 7507 long - - E_TYPE 9009 long - - E_CODE 9010 long - - E_MSG 9011 string - - E_TMP 9012 long - -
Tmax 환경설정
다음은 Tmax 환경설정 파일의 예제이다.
<tmconfig.m>
*DOMAIN dom1 SHMKEY = 70000, MAXUSER = 200, MINCLH = 1, MAXCLH = 5, TPORTNO = 8888, BLOCKTIME = 200, TXTIME = 200 *NODE tmax1 TMAXDIR = "/home/tmax", APPDIR = "/home/tmax/appbin", PATHDIR = "/home/tmax/path", TLOGDIR = "/home/tmax/log/tlog", SLOGDIR = "/home/tmax/log/slog" ULOGDIR = "/home/tmax/log/ulog" *SVRGROUP svg1 NODENAME = tmax1, DBNAME = ORACLE, OPENINFO = "ORACLE_XA+Acc=P/scott/tiger+SesTm=60", TMSNAME = svg1_tms *SERVER emp_c SVGNAME = svg1, MIN = 1 *SERVICE FDLSELECT VRNAME = emp_c FDLUPDATE SVRNAME = emp_c FDLDELETE SVRNAME = emp_c FDLINSERT SVRNAME = emp_c
3.4. 클라이언트 프로그램
메인화면 Form
다음은 메인 화면 Form 디자인 화면이다.
다음은 예제에서 사용할 메인화면 Form 디자인 구성표이다.
컨트롤명 | 컨트롤 종류 | 비고 |
---|---|---|
EmployeeMgr |
Form |
Caption="사원관리 프로그램" |
LabelErr |
라벨 |
Caption="오류" |
BtnExit |
커맨드 버튼 |
Caption="종료" |
BtnIns |
커맨드 버튼 |
Caption="입력" |
BtnDel |
커맨드 버튼 |
Caption="수정" |
BtnUdt |
커맨드 버튼 |
Caption="조회" |
BtnSel |
커맨드 버튼 |
|
EditName |
텍스트 박스 |
|
EditEmpNo |
텍스트 박스 |
|
EditDept |
텍스트 박스 |
|
EditComm |
텍스트 박스 |
|
EditSal |
텍스트 박스 |
|
EditDate |
텍스트 박스 |
|
EditMgr |
텍스트 박스 |
|
EditJob |
텍스트 박스 |
다음은 메인 화면 Form 디자인을 실행하기 위한 예제이다.
EmployeeMgr.frm Source Option Explicit Private Sub BtnDel_Click() Dim Isendbuf As Long Dim Irecvbuf As Long Dim Irbuflen As Long Dim Iret As Long Dim text As String Dim value As Long Dim dvalue As Double Dim svalue As Single Dim tx_b As Integer Dim txbool As Integer ' 트랜잭션이 시작되면 1, 아니면 0 ' ' tpstart ' tmaxStart ' 트랜잭션 시작 유무 초기화 ' txbool = 0 If EditEmpNo.text = "" Then MsgBox "사원번호를 입력해 주세요." tmaxEnd Exit Sub End If value = Trim(EditEmpNo.text) ' 보낼 데이터를 위한 버퍼 할당 ' Isendbuf = fballoc(100, 1024) If Isendbuf = Null Then TmaxError ("fballoc") Call fbfree(Isendbuf) tmaxEnd Exit Sub End If ' 받을 데이터를 위한 버퍼 할당 ' Irecvbuf = fballoc(100, 1024) If Irecvbuf = Null Then TmaxError ("fballoc") Call fbfree(Irecvbuf) tmaxEnd Exit Sub End If Iret = PUTLONG(ByVal Isendbuf, "EMPNO", 0, value) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 트랜잭션 시작 ' Iret = tx_begin txbool = 1 If Iret < 0 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 조회 서비스를 요청 ' Iret = tpcall(ByVal "FDLDELETE", ByVal Isendbuf, ByVal 0, Irecvbuf, Irbuflen, ByVal 0) LabelErr.Caption = "sbuf = " & Isendbuf & ", rbuf = " & Irecvbuf If Iret = -1 Then TmaxError ("tpcall(SVC1)") ViewErr (Irecvbuf) Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 트랜잭션 저장 ' Iret = tx_commit If Iret < 0 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) Else txbool = 1 Call ExitSub(txbool, Isendbuf, Irecvbuf) End If End Sub Private Sub BtnExit_Click() End End Sub Private Sub BtnIns_Click() Dim Isendbuf As Long Dim Irecvbuf As Long Dim Irbuflen As Long Dim Iret As Long Dim text As String Dim value As Long Dim dvalue As Double Dim svalue As Single Dim lenL As Long Dim txbool As Integer ' 트랜잭션이 시작되면 1, 아니면 0 ' ' tpstart ' tmaxStart ' 트랜잭션 시작 유무 초기화 ' txbool = 0 If EditEmpNo.text = "" Then MsgBox "사원번호를 입력해 주세요." tmaxEnd Exit Sub End If ' 보낼 데이터를 위한 버퍼 할당 ' Isendbuf = fballoc(100, 1024) If Isendbuf = Null Then TmaxError ("fballoc") Call fbfree(Isendbuf) tmaxEnd Exit Sub End If ' 받을 데이터를 위한 버퍼 할당 ' Irecvbuf = fballoc(100, 1024) If Irecvbuf = Null Then TmaxError ("fballoc") Call fbfree(Irecvbuf) tmaxEnd Exit Sub End If Iret = PUTLONG(ByVal Isendbuf, "EMPNO", 0, Trim(EditEmpNo.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTVAR(ByVal Isendbuf, "ENAME", 0, Trim(EditName.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTVAR(ByVal Isendbuf, "JOB", 0, Trim(EditJob.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTLONG(ByVal Isendbuf, "MGR", 0, Trim(EditMgr.text)) If Iret = -1 Then ' 트랜잭션 시작 ' Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTVAR(ByVal Isendbuf, "DATE", 0, Trim(EditDate.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If svalue = Trim(EditSal.text) ' fbput, fbget_fldkey 함수의 정의는 comm.bas 파일에 정의되어 있습니다. ' ' fbget_fldkey 함수는 필드명을 키값으로 변환해 줍니다. ' Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("SAL"), svalue, ByVal lenL) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 밑의 주석부분은 주석 다음문과 같은 기능을 할 수 있습니다. ' 'svalue = Trim(EditComm.text) 'Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("COMM"), svalue, ByVal lenL) 'If Iret = -1 Then ' FdlErrorMsg ("fbput") ' Exit Sub 'End If ' 위의 주석과 같은 기능을 합니다. ' Iret = PUTFLOAT(ByVal Isendbuf, "COMM", 0, Trim(EditComm.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTLONG(ByVal Isendbuf, "DEPTNO", 0, Trim(EditDept.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 트랜잭션 시작 ' Iret = tx_begin txbool = 1 If Iret < 0 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 수정 서비스를 요청 ' Iret = tpcall(ByVal "FDLINSERT", ByVal Isendbuf, ByVal 0, Irecvbuf, Irbuflen, ByVal 0) LabelErr.Caption = "sbuf = " & Isendbuf & ", rbuf = " & Irecvbuf If Iret = -1 Then TmaxError ("tpcall(SVC1)") ViewErr (Irecvbuf) Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 트랜잭션 저장 ' Iret = tx_commit If Iret < 0 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) Else txbool = 1 Call ExitSub(txbool, Isendbuf, Irecvbuf) End If End Sub ' Oracle에 대한 에러를 출력해주는 함수 ' ' 조회 버튼을 클릭시 이벤트 핸들러 ' Private Sub BtnSel_Click() Hide ' 조회 결과 창 표시하기 ' EmployeeGrid.Show End Sub ' 수정 버튼을 클릭시 이벤트 핸들러 ' Private Sub BtnUdt_Click() Dim Isendbuf As Long Dim Irecvbuf As Long Dim Irbuflen As Long Dim Iret As Long Dim text As String Dim value As Long Dim dvalue As Double Dim svalue As Single Dim lenL As Long Dim txbool As Integer ' 트랜잭션이 시작되면 1, 아니면 0 ' ' tpstart ' tmaxStart ' 트랜잭션이 시작 유무 초기화 ' txbool = 0 If EditEmpNo.text = "" Then MsgBox "사원번호를 입력해 주세요." tmaxEnd Exit Sub End If ' 보낼 데이터를 위한 버퍼 할당 ' Isendbuf = fballoc(100, 1024) If Isendbuf = Null Then TmaxError ("fballoc") Call fbfree(Isendbuf) tmaxEnd Exit Sub End If ' 받을 데이터를 위한 버퍼 할당 ' Irecvbuf = fballoc(100, 1024) If Irecvbuf = Null Then TmaxError ("fballoc") Call fbfree(Irecvbuf) tmaxEnd Exit Sub End If Iret = PUTLONG(ByVal Isendbuf, "EMPNO", 0, Trim(EditEmpNo.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTVAR(ByVal Isendbuf, "ENAME", 0, Trim(EditName.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTVAR(ByVal Isendbuf, "JOB", 0, Trim(EditJob.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTLONG(ByVal Isendbuf, "MGR", 0, Trim(EditMgr.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTVAR(ByVal Isendbuf, "DATE", 0, Trim(EditDate.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If svalue = Trim(EditSal.text) ' Declare Function fbput Lib "TMAX4GL.DLL" (ByVal pFBUF As Long, ByVal fieldid As Long, pbuffer As Any, ByVal Fieldlen As Long) As Long Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("SAL"), svalue, ByVal lenL) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If svalue = Trim(EditComm.text) Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("COMM"), svalue, ByVal lenL) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If Iret = PUTLONG(ByVal Isendbuf, "DEPTNO", 0, Trim(EditDept.text)) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 트랜잭션 시작 ' Iret = tx_begin txbool = 1 If Iret < 0 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 수정 서비스를 요청 ' Iret = tpcall(ByVal "FDLUPDATE", ByVal Isendbuf, ByVal 0, Irecvbuf, Irbuflen, ByVal 0) LabelErr.Caption = "sbuf = " & Isendbuf & ", rbuf = " & Irecvbuf If Iret = -1 Then TmaxError ("tpcall(SVC1)") ViewErr (Irecvbuf) Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 트랜잭션 저장 ' Iret = tx_commit If Iret < 0 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) Else txbool = 1 Call ExitSub(txbool, Isendbuf, Irecvbuf) End If End Sub Private Sub ExitSub(txbool As Integer, Isendbuf As Long, Irecvbuf As Long) If txbool = 1 Then tx_rollback End If ' 할당된 버퍼 해제 ' Call fbfree(ByVal Isendbuf&) Call fbfree(ByVal Irecvbuf&) ' tpend 실행 함수 ' tmaxEnd Exit Sub End Sub ' tpstart ' Private Sub tmaxStart() Dim ret As Integer ' 환경설정 파일을 불러옵니다. ' ' atmi.bas 파일에 정의되어 있습니다. ' ' Declare Function tmaxreadenv Lib "TMAX4GL.DLL" (ByVal envfile As String, ByVal label As String) As Long ' ' 자세한 설명은 "Tmax Reference Guide"를 참고하십시오. ' ret = tmaxreadenv("C:\tmax.env", "aix5l389") If ret < 0 Then TmaxError ("tmaxreadenv") Exit Sub End If ret = tpstart(ByVal 0&) If ret = -1 Then LabelErr.Caption = "tpstart error = " & gettperrno() TmaxError ("tpstart") Exit Sub Else LabelErr.Caption = "tpstart return value = " & ret & " tpstart success" End If End Sub ' tpend ' Private Sub tmaxEnd() Dim ret As Integer ret = tpend() If ret = -1 Then LabelErr.Caption = "tpend error = " & gettperrno() TmaxError ("tpend") Exit Sub Else LabelErr.Caption = "tpreturn return value = " & ret End If End Sub
Oracle 에러 출력
다음은 Oracle 에러 출력 화면이다.
다음은 Oracle 에러 출력 화면을 실행하는 데 필요한 환경설정의 예제이다.
' Oracle에 대한 에러를 출력해주는 함수 ' Private Sub ViewErr(ByVal a As Long) 'E_TYPE 9009 long - - 'E_CODE 9010 long - - 'E_MSG 9011 string - - 'E_TMP 9012 long - - Dim typeL, codeL, tmpL As Long Dim msgS As String Dim Iret As Integer ' Tmax FDL Reference Guide 참조 ' ' comm.bas에 함수가 정의되어 있음 ' Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_TYPE"), 0, typeL, 0) If Iret = -1 Then FdlErrorMsg ("fbget_tu") Exit Sub End If Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_CODE"), 0, codeL, 0) If Iret = -1 Then FdlErrorMsg ("fbget_tu") Exit Sub End If Iret = GETVAR(ByVal a, "E_MSG", 0, msgS) If Iret = -1 Then TmaxError ("ViewErr, GETVAR, E_MSG") Exit Sub End If Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_TMP"), 0, tmpL, 0) If Iret = -1 Then FdlErrorMsg ("fbget_tu") Exit Sub End If ' 에러를 메시지 박스로 보여줌 ' MsgBox ("Error Type : " & typeL & " ,Code : " & codeL & " ,Message : " & msgS & " ,Tmp : " & tmpL) End Sub
사원 조회 화면
다음은 사원 조회 화면 Form 디자인 화면이다.
다음은 조회 화면 Form 디자인 구성표이다.
컨트롤 이름 | 컨트롤 종류 | 수정이 필요한 프로퍼티 |
---|---|---|
EmployeeGrid |
Form |
Caption="사원정보 목록" |
InfoText |
텍스트 박스 |
MultiLine=True |
BtnReturn |
커맨드 버튼 |
Caption="돌아가기" |
다음은 조회 화면 Form 디자인 화면을 실행하는 데 필요한 환경설정의 예제이다.
EmployeeGrid.frm Source LabelErr Option Explicit ' 조회 창을 닫기 ' Private Sub BtnReturn_Click() Hide EmployeeMgr.Show End Sub ' 조회 버튼 Click시 조회 리스트 결과를 보여줄 함수 ' Private Sub Form_Activate() Dim Isendbuf As Long Dim Irecvbuf As Long Dim Irbuflen As Long Dim Iret As Integer Dim text As String Dim value As Long Dim dvalue As Double Dim svalue As Single Dim lenL As Long Dim initS, outputS As String Dim empnoS, enameS, jobS, mgrS, dateS, salS, commS, deptnoS As String Dim cntL As Long Dim eNo As Long Dim txbool As Integer ' 트랜잭션이 시작되면 1, 아니면 0 ' ' tpstart ' tmaxStart ' 트랜잭션 시작 유무 초기화 ' txbool = 0 initS = vbCrLf & vbTab & vbTab & vbTab & "***** 검색결과 *****" & vbCrLf & vbTab & "===================================================" & vbCrLf & vbTab & "사원번호 이름 직책 담당임원 입사일 봉급 COMM 부서" & vbCrLf & vbTab & "===================================================" & vbCrLf & vbCrLf If EmployeeMgr.EditEmpNo.text = "" Then MsgBox "사원번호를 입력해 주세요." Hide EmployeeMgr.Show Exit Sub End If ' 보낼 데이터를 위한 버퍼 할당 ' Isendbuf = fballoc(100, 1024) If Isendbuf = Null Then TmaxError ("fballoc") Call fbfree(Isendbuf) tmaxEnd Exit Sub End If ' 받을 데이터를 위한 버퍼 할당 ' Irecvbuf = fballoc(100, 1024) If Irecvbuf = Null Then TmaxError ("fballoc") Call fbfree(Irecvbuf) tmaxEnd Exit Sub End If ' 사원관리 Form에서 사원번호를 가지고 옵니다. eNo = Trim(EmployeeMgr.EditEmpNo.text) Iret = fbput(ByVal Isendbuf, ByVal fbget_fldkey("EMPNO"), eNo, ByVal lenL) If Iret = -1 Then Call ExitSub(txbool, Isendbuf, Irecvbuf) End If ' 조회 서비스를 요청 ' Iret = tpcall(ByVal "FDLSELECT", ByVal Isendbuf, ByVal 0, Irecvbuf, Irbuflen, ByVal 0) If Iret = -1 Then ViewErr (Irecvbuf) Call ExitSub(txbool, Isendbuf, Irecvbuf) End If cntL = fbkeyoccur(ByVal Irecvbuf, ByVal fbget_fldkey("EMPNO")) Dim i As Long For i = 0 To cntL - 1 Iret = GETLONG(ByVal Irecvbuf, "EMPNO", i, value) If Iret = -1 Then TmaxError ("GETLONG(EMPNO)") Call ExitSub(txbool, Isendbuf, Irecvbuf) End If empnoS = value Iret = GETVAR(ByVal Irecvbuf, "ENAME", i, text) If Iret = -1 Then TmaxError ("GETVAR(ENAME)") Call ExitSub(txbool, Isendbuf, Irecvbuf) End If enameS = text Iret = GETVAR(ByVal Irecvbuf, "JOB", i, text) If Iret = -1 Then TmaxError ("GETVAR(JOB)") Call ExitSub(txbool, Isendbuf, Irecvbuf) End If jobS = text Iret = GETLONG(ByVal Irecvbuf, "MGR", i, value) If Iret = -1 Then TmaxError ("GETLONG(MGR)") Call ExitSub(txbool, Isendbuf, Irecvbuf) End If mgrS = value Iret = GETVAR(ByVal Irecvbuf, "DATE", i, text) If Iret = -1 Then TmaxError ("GETVAR(DATE)") Call ExitSub(txbool, Isendbuf, Irecvbuf) End If dateS = text ' SAL 데이터 필드에서 float 데이터를 가져옵니다. ' ' comm.bas에 함수가 정의되어 있습니다. ' Iret = fbget_tu(ByVal Irecvbuf, ByVal fbget_fldkey("SAL"), i, svalue, 0) If Iret = -1 Then FdlErrorMsg ("fbget_tu") Call ExitSub(txbool, Isendbuf, Irecvbuf) End If salS = svalue Iret = GETFLOAT(ByVal Irecvbuf, "COMM", i, svalue) If Iret = -1 Then TmaxError ("GETFLOAT(COMM)") Call ExitSub(txbool, Isendbuf, Irecvbuf) End If commS = svalue Iret = GETLONG(ByVal Irecvbuf, "DEPTNO", i, value) If Iret = -1 Then TmaxError ("GETLONG(DEPTNO)") Call ExitSub(txbool, Isendbuf, Irecvbuf) End If deptnoS = value & vbCrLf outputS = outputS & " " & empnoS & vbTab & enameS & vbTab & jobS & vbTab & mgrS & vbTab & dateS & vbTab & salS & vbTab & commS & vbTab & deptnoS Next i InfoText.text = initS & outputS ' 반환된 데이터를 텍스트 박스에 출력 ' LabelErr.Caption = "SAL = " & dvalue Call ExitSub(txbool, Isendbuf, Irecvbuf) End Sub Private Sub ExitSub(txbool As Integer, Isendbuf As Long, Irecvbuf As Long) If txbool = 1 Then tx_rollback End If ' 할당된 버퍼 해제 ' Call fbfree(ByVal Isendbuf&) Call fbfree(ByVal Irecvbuf&) ' tpend 실행 함수 ' tmaxEnd Exit Sub End Sub ' tpstart ' Private Sub tmaxStart() Dim ret As Integer ' 환경설정 파일을 불러옵니다. ' ' atmi.bas 파일에 정의되어 있습니다. ' ' Declare Function tmaxreadenv Lib "TMAX4GL.DLL"(ByVal envfile As String, ByVal label As String) As Long ' ' 자세한 설명은 "Tmax Reference Guide"를 참고하십시오. ' ret = tmaxreadenv("C:\tmax.env", "aix5l389") If ret < 0 Then TmaxError ("tmaxreadenv") Exit Sub End If ret = tpstart(ByVal 0&) If ret = -1 Then LabelErr.Caption = "tpstart error = " & gettperrno() TmaxError ("tpstart") Exit Sub Else LabelErr.Caption = "tpstart return value = " & ret & " tpstart success" End If End Sub ' tpend ' Private Sub tmaxEnd() Dim ret As Integer ret = tpend() If ret = -1 Then LabelErr.Caption = "tpend error = " & gettperrno() TmaxError ("tpend") Exit Sub Else LabelErr.Caption = "tpreturn return value = " & ret End If End Sub ' Oracle에 대한 에러를 출력해주는 함수 ' Private Sub ViewErr(ByVal a As Long) 'E_TYPE 9009 long - - 'E_CODE 9010 long - - 'E_MSG 9011 string - - 'E_TMP 9012 long - - Dim typeL As Long Dim codeL As Long Dim msgS As String Dim tmpL As Long Dim Iret As Integer Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_TYPE"), 0, typeL, 0) If Iret = -1 Then FdlErrorMsg ("fbget_tu") Exit Sub End If Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_CODE"), 0, codeL, 0) If Iret = -1 Then FdlErrorMsg ("fbget_tu") Exit Sub End If Iret = GETVAR(ByVal a, "E_MSG", 0, msgS) Iret = fbget_tu(ByVal a, ByVal fbget_fldkey("E_TMP"), 0, tmpL, 0) If Iret = -1 Then FdlErrorMsg ("fbget_tu") Exit Sub End If MsgBox ("Error Type : " & typeL & " ,Code : " & codeL & " ,Message : "&msgS&" ,Tmp : " & tmpL) End Sub
3.5. 서버 프로그램
서비스 프로그램
다음은 서비스 프로그램의 예제이다.
<emp_c.pc>
#include <stdio.h> #include <ctype.h> #include <tuxinc/macro.h> #include "../../fdl/demo_fdl.h" EXEC SQL include sqlca.h; EXEC SQL INCLUDE ORACA; EXEC ORACLE OPTION (ORACA=YES); EXEC ORACLE OPTION (RELEASE_CURSOR=YES); #define INP 1 #define ORA 2 #define TMX 3 #define APP 4 EXEC SQL begin declare section; int h_empno; char h_ename[11]; char h_job[10]; int h_mgr; char h_date[11]; float h_sal; float h_comm; int h_deptno; EXEC SQL end declare section; void svc_error(long type, long err_code, char *msg, long tmp); FDLINSERT( TPSVCINFO *msg ) { FBUF *rcvbuf; int i, occurrence; rcvbuf = (FBUF *)msg->data; h_empno = h_mgr = h_sal = h_comm = h_deptno = 0; memset(h_ename, 0x00, sizeof(h_ename)); memset(h_job, 0x00, sizeof(h_job)); memset(h_date, 0x00, sizeof(h_date)); occurrence = fbkeyoccur(rcvbuf, EMPNO); for (i=0; i< occurrence; i++){ fbget_tu(rcvbuf, EMPNO, i, (char *)&h_empno, 0); fbget_tu(rcvbuf, MGR, i, (char *)&h_mgr, 0); fbget_tu(rcvbuf, SAL, i, (char *)&h_sal, 0); fbget_tu(rcvbuf, COMM, i, (char *)&h_comm, 0); fbget_tu(rcvbuf, DEPTNO,i, (char *)&h_deptno, 0); fbget_tu(rcvbuf, ENAME, i, (char *)h_ename, 0); fbget_tu(rcvbuf, JOB , i, (char *)h_job, 0); fbget_tu(rcvbuf, DATE , i, (char *)h_date, 0); EXEC SQL INSERT INTO emp(empno, ename, job, mgr, hiredate, sal,comm, deptno) VALUES (:h_empno, :h_ename, :h_job, :h_mgr, to_date(:h_date,'yyyymmdd'), :h_sal, :h_comm, :h_deptno ); } if(sqlca.sqlcode != 0) goto LB_DBERROR; EXEC SQL WHENEVER SQLERROR goto LB_DBERROR; tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L); LB_DBERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0); } FDLDELETE( TPSVCINFO *msg ) { FBUF *rcvbuf; int i, occurrence; rcvbuf = ( FBUF *)msg->data; occurrence = fbkeyoccur(rcvbuf, EMPNO); for (i=0; i< occurrence; i++){ fbget_tu (rcvbuf, EMPNO, i, (char *)&h_empno , 0); EXEC SQL DELETE FROM emp WHERE empno = :h_empno; } if(sqlca.sqlcode != 0) goto LB_DBERROR; EXEC SQL WHENEVER SQLERROR goto LB_DBERROR ; EXEC SQL WHENEVER NOT FOUND goto LB_DBERROR ; tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L); LB_DBERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0); } FDLSELECT( TPSVCINFO *msg ) { FBUF *rcvbuf; FLDLEN fldlen; int i=0, ROWMEM=200, CHKROW=500; rcvbuf = (FBUF *)msg->data; if((rcvbuf=(FBUF *)tprealloc((char *)rcvbuf,ROWMEM*CHKROW))==NULL) { rcvbuf=(FBUF *)msg->data; goto LB_TMAXERROR ; } h_empno = h_mgr = h_sal = h_comm = h_deptno = 0; memset( h_ename, 0x00, sizeof( h_ename ) ); memset( h_job, 0x00, sizeof( h_job ) ); memset( h_date, 0x00, sizeof( h_date ) ); fbget_tu( rcvbuf, EMPNO, 0, (char *)&h_empno, &fldlen); EXEC SQL DECLARE DB_CUR CURSOR FOR SELECT nvl(empno,0), nvl(ename,' '), nvl(job,' '), nvl(to_char(hiredate,'yyyymmdd'),' '), nvl(mgr,0), nvl(sal,0), nvl(comm,0), nvl(deptno,0) FROM emp WHERE empno >= :h_empno-50 AND empno <= :h_empno+50; EXEC SQL OPEN DB_CUR; if(sqlca.sqlcode != 0) goto LB_DBERROR; EXEC SQL WHENEVER SQLERROR goto LB_DBERROR ; EXEC SQL WHENEVER NOT FOUND Do break ; while(1) { EXEC SQL FETCH DB_CUR INTO :h_empno, :h_ename, :h_job, :h_date, :h_mgr, :h_sal, :h_comm, :h_deptno; fbchg_tu(rcvbuf, EMPNO, i,(char *)&h_empno, 0); fbchg_tu(rcvbuf, MGR, i,(char *)&h_mgr, 0); fbchg_tu(rcvbuf, SAL, i,(char *)&h_sal, 0); fbchg_tu(rcvbuf, DEPTNO, i,(char *)&h_deptno, 0); fbchg_tu(rcvbuf, COMM, i,(char *)&h_comm, 0); fbchg_tu(rcvbuf, ENAME, i,(char *)h_ename, 0); fbchg_tu(rcvbuf, JOB, i,(char *)h_job, 0); fbchg_tu(rcvbuf, DATE, i,(char *)h_date, 0); i++; } if (i < 1) goto LB_DBERROR; EXEC SQL CLOSE DB_CUR; tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L); LB_DBERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL CLOSE DB_CUR ; svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0L) ; LB_TMAXERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL CLOSE DB_CUR; svc_error(TMX, tperrno, "", 0L); } FDLUPDATE( TPSVCINFO *msg ) { FBUF *rcvbuf ; int i, occurrence; rcvbuf = (FBUF *)msg->data; h_empno = h_mgr = h_sal = h_comm = h_deptno = 0; memset( h_ename, 0x00, sizeof( h_ename ) ); memset( h_job, 0x00, sizeof( h_job ) ); memset( h_date, 0x00, sizeof( h_date ) ); occurrence = fbkeyoccur(rcvbuf, EMPNO); for (i=0; i< occurrence; i++){ fbget_tu ( rcvbuf, EMPNO, i, (char *)&h_empno, 0); fbget_tu ( rcvbuf, ENAME, i, (char *)h_ename, 0); fbget_tu ( rcvbuf, JOB, i, (char *)h_job, 0); fbget_tu ( rcvbuf, MGR, i, (char *)&h_mgr, 0); fbget_tu ( rcvbuf, SAL, i, (char *)&h_sal, 0); fbget_tu ( rcvbuf, COMM, i, (char *)&h_comm,0); fbget_tu ( rcvbuf, DEPTNO, i, (char *)&h_deptno,0); fbget_tu ( rcvbuf, DATE, i, (char *)h_date, 0); EXEC SQL UPDATE emp SET ename = nvl(:h_ename, ename), job = nvl(:h_job, job), mgr = :h_mgr, hiredate = nvl(to_date(:h_date, 'yyyymmdd'),hiredate), sal = :h_sal, comm = :h_comm, deptno = :h_deptno WHERE empno = :h_empno; if(sqlca.sqlcode != 0) goto LB_DBERROR; EXEC SQL WHENEVER SQLERROR goto LB_DBERROR; EXEC SQL WHENEVER NOT FOUND goto LB_DBERROR; } tpreturn(TPSUCCESS, 0L, (char *)rcvbuf, 0L, 0L); LB_DBERROR : EXEC SQL WHENEVER SQLERROR CONTINUE; svc_error(ORA, sqlca.sqlcode, sqlca.sqlerrm.sqlerrmc, 0L) ; } /********************************************************************* * 에러처리 : 서비스에서 오류가 발생하면 그 오류를 버퍼에 넣어 클라이언트로 보내준다. ********************************************************************/ void svc_error(long type, long err_code, char *msg, long tmp) { FBUF *transf; char *svcname; char err_msg[100]; char temp[100]; int i = 0; printf("type ==>[%ld]\n", type); printf("err_code ==>[%ld]\n", err_code); printf("msg ==>[%s]\n", msg); strcpy(err_msg, msg); if ((transf = (FBFR *)tpalloc("FML", NULL, 0)) == NULL) { printf("tpalloc failed! errno = %d\n", tperrno); } switch(type) { case INP: switch(err_code) { case -1000: strcpy(err_msg,"해당 사용자에게 권한이 없습니다."); break; default: strcpy(err_msg, "Input Error Message가 등록되어 있지 않습니다."); } break; case ORA: if (strlen(err_msg)== 0) strcpy(err_msg, sqlca.sqlerrm.sqlerrmc); break; case TMX: if (strlen(err_msg)== 0) strcpy(err_msg, tpstrerror(tperrno)); break; case APP: if (strlen(err_msg)== 0) { /* err_mssg=""이면 오류메세지를 setting한다. ******/ switch(err_code) { case -500: /* SYSTEM 관련 오류 */ strcpy(err_msg,"File 생성 오류입니다."); break; case -502: strcpy(err_msg,"내부 서비스를 호출하지 못했습니다."); break; case -504: strcpy(err_msg, "소켓 통신 오류입니다."); break; case -505: /* 다른 transation에서 수정되었을 경우 MSG처리*/ /* "조회 이후에 다른 곳에서 [%s]자료가 변경되었습니다. \n\n다시 조회한 후 처리하십시오.": CLIENT에서 처리*/ strcpy(err_msg,"이 없습니다."); break; case -5002: strcpy(err_msg, "전산실에 문의하십시오."); break; default: strcpy(err_msg, "Application Error Message가 등록되어 있지 않습니다."); } } break; } /* ROLLBACK */ EXEC SQL WHENEVER SQLERROR CONTINUE; EXEC SQL ROLLBACK; fbchg_tu ( transf, E_TYPE, i, (char *)&type,0); fbchg_tu ( transf, E_CODE, i, (char *)&err_code,0); fbchg_tu ( transf, E_MSG, i, (char *)err_msg,0); fbchg_tu ( transf, E_TMP, i, (char *)&tmp,0); tpreturn(TPFAIL, 0, (char *)transf, 0L, 0L); }
Makefile
다음은 emp_c.pc 소스를 Tmax 애플리케이션으로 만드는 Makefile의 예제이다.
<emp_c.mk>
include $(ORACLE_HOME)/precomp/lib/env32.mk ORALIBDIR = $(LIBHOME) ORALIB = -L/home/oracle/OraHome/lib32/ -lclntsh -lld -lm `cat /home/oracle/OraHome/lib32/sysliblist` -lm -lc_r -lpthreads TARGET = emp_c APOBJS = emp_c.o NSDLOBJ = $(TMAXDIR)/lib/sdl.o #CC CC=cc #Oracle LIBS = -lsvr -loras OBJS = $(APOBJS) $(SVCTOBJ) SVCTOBJ = $(TARGET)_svctab.o CFLAGS = -q32 -O -I$(TMAXDIR) LDFLAGS = -brtl APPDIR = $(TMAXDIR)/appbin SVCTDIR = $(TMAXDIR)/svct TMAXLIBDIR = $(TMAXDIR)/lib # .SUFFIXES : .c .c.o: $(CC) $(CFLAGS) $(LDFLAGS) -c $< all: $(TARGET) $(TARGET): $(OBJS) $(CC) $(CFLAGS) $(LDFLAGS) -L$(TMAXLIBDIR) -o $(TARGET) -L$(ORALIBDIR) $(ORALIB) $(OBJS) $(LIBS) $(NSDLOBJ) mv $(TARGET) $(TMAXDIR)/appbin $(APOBJS): $(TARGET).pc proc iname=emp_c include=$(TMAXDIR) define=__LINUX_ORACLE_PROC__ $(CC) $(CFLAGS) $(LDFLAGS) -c $(TARGET).c $(SVCTOBJ): touch $(SVCTDIR)/$(TARGET)_svctab.c $(CC) $(CFLAGS) $(LDFLAGS) -c $(SVCTDIR)/$(TARGET)_svctab.c # clean: -rm -f *.o core $(TARGET) $(TARGET).lis