Pro*C 파헤치기

DB/Oracle 2012. 2. 24. 23:38

proc 파헤치기

윤 상배

dreamyun@yahoo.co.kr



1절. 소개

proc 프로그래밍은 간단히 다룰수 있는 주제가 아니다. 그럭저럭 다루려고 한다고 해도 책한권 분량은 다루어야할 주제이다.

그러므로 몇번의 문서에 걸쳐서 proc 프로그래밍에 대한 내용을 다룰것이다. 그렇다고 해서 시중에 나와있는 proc 레퍼런스 수준의 방대하고 세밀한 내용을 다룰것을 기대하지는 말기 바란다. 이 사이트의 대부분의 문서들이 그렇듯이 초기에 문제에 쉽게 접근할수 있는 지침서 역활수준에서 작성될것이다.

깊이 있는 내용은 자신이 직접 - 시중의 책을 이용하던지, 아니면 프로젝트를 진행하든지 - 익혀나가도록 해야 할것이다.

이번장에서는 proc 에 대한 간략한 소개와 프로그래밍을 위한 환경설명과, 환경준비과정 그리고 간단한 셈플예제와 이 셈플을 제대로 컴파일 하기 위한 Makefile 제작등에 대해서 알아볼 것이다.

이 문서는 여러분이 적어도 오라클은 설치할줄알고, 기본적인 몇가지 환경정보들은 알고 있다는 가정하에 씌여지게 될것이다. 또한 오라클 817 버젼을 기준으로 작성될것이다. 다른 버젼의 오라클의 경우 경로등에서 약간의 차이가 있을수 있을것이다.


2절. 오라클 서버/클라이언트 환경만들기

proc 프로그래밍을 하기 위해서는 우선적으로 테스트 환경이 만들어져 있어야 한다. 오라클 서버는 이미 설치되어서 가동중에 있다고 가정을 하겠다. 설치 문서는오라클817 설치하기를 참조하기 바란다.

우리가 proc 를 이용해서 만들고자 하는 프로그램은 c/s 모델기반으로 클라이언트로 작동하게 될것이다. 서버는 오라클이 될것이며, 클라이언트로써 오라클 서버에 접근해서 원하는 정보를 가져오는 프로그램을 만들것이다.

서버/클라이언트 프로그래밍 환경에 있어서 가장 기본적인 것은 서버와 클라이언트의 네트웍 설정을 하는 것이다. 서버측 프로그램은 연결을 받아들일 클라이언트의 주소영역과 포트를 지정하고 클라이언트측에서는 연결을할 서버의 주소영역과 포트번호를 역시 지정해야 할것이다.

일반적인 c/s 모델 프로그램에서는 이러한 정보를 클라이언트 프로그램과 서버 프로그램이 가지고 있지만 오라클의 경우 이러한 네트웍 정보를 자체적으로 유지한다. 이게 바로 listener 와 tnsname 이라는 것이다.

이제 listener 와 tnsname 에 대해서 자세히 알아보도록 하겠다. 참.. 물론 그전에 오라클 서버를 가동 시켜놓아야 한다.


2.1절. 오라클 서버 가동

oracle 계정으로 스위치 유저한다음에 svrmgrl 을 이용하면 간단하게 오라클 서버를 가동시킬수 있다.

Server Manager complete.
[oracle@localhost admin]$ svrmgrl

Oracle Server Manager Release 3.1.7.0.0 - Production

Copyright (c) 1997, 1999, Oracle Corporation.  All Rights Reserved.

Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

SVRMGR> connect internal
Connected.
SVRMGR> startup
ORACLE instance started.
Total System Global Area                         93675680 bytes
...
...
Database opened.
SVRMGR> 
			
SVRMGR 프롬프트가 떨어지고 나면 connect internal -> startup 으로 오라클을 가동시킬수 있다. 중지는 connect internal -> shutdown 이다.


2.2절. listener (서버측 설정)

아마도 listener 이라는 단어에서 대충 어떤 일을 하는 것인지 유추할수 있을것이다. 즉 네트웍 서버로써 외부의 연결이 있는지 대기 하고 있다가 연결이 있으면 연결을 받아들이는 역활을 한다. 연결을 받고 나면 몇가지 처리를 한후 클라이언트를 위한 오라클 인스턴스를 할당하고 만들어진 인스턴스를 이용해서 클라이언트와 대화하게 된다.

이러한 과정을 완전히 이해할려면 더 많은 내용이 보충되어야 하겠지만 이 문서는 DBA 를 위한 문서는 아님으로 이런거다 라는 정도로 이해하는 수준에서 넘어가도록 하겠다. 좀더 깊이 있는 내용에 관심이 있다면 관련 책을 사서 공부해야 할것이다.

간단히 말하자면 listener 은 인터넷 서비스를 위한 오라클 프로세스 라고 생각할수 있는데, 모든 (제대로된) 서버 프로그램이 그렇듯이 이 listener 역시 설정 파일을 가지고 있다.


2.2.1절. listener 설정

$ORACLE_HOME/network/admin/listener.ora 가 바로 listener 설정 파일이다. 다음은 필자의 listener 의 초기 설정치 내용이다.

LISTENER =
  (DESCRIPTION_LIST =
    (DESCRIPTION =
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
      )
      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
      )
    )
  )

SID_LIST_LISTENER =
  (SID_LIST =
    (SID_DESC =
      (SID_NAME = PLSExtProc)
      (ORACLE_HOME = /usr/u01/product/8.1.7)
      (PROGRAM = extproc)
    )
    (SID_DESC =
      (GLOBAL_DBNAME = oracle)
      (ORACLE_HOME = /usr/u01/product/8.1.7)
      (SID_NAME = oracle)
    )
  )
				
그리 이해하기 어렵지 않을 것이다. 크게 2개의 섹션으로 이루어 져있는데 LISTENER 섹션은 연결을 받아들일 클라이언트를 위한 호스트 IP 와 PORT 지정을 위한 내용을 SID_LIST_LISTENER 은 서비스할 DB 의 정보를 가지고 있다.

초기에는 단지 localhost(127.0.0.1) 에서의 접근과 내부(IPC) 접근 만을 위한 설정이 되어있다. 기본적으로 오라클은 포트번호 1521 을 사용한다. 어드레스가 더 추가된다면

      (ADDRESS_LIST =
        (ADDRESS = (PROTOCOL = TCP)(HOST = xxx.xxx.xxx.xxx)(PORT = 1521))
      )
				
이런 식으로 목록을 써나가면 된다.

서비스하는 DB 는 최초에 우리가 만들었던 oracle 이 서비스 될것이다. 마찬가지로 서비스할 DB 목록을 계속적으로 추가해 나갈수 있다.


2.2.2절. listener 가동

listener.ora 설정을 마쳤다면(우선은 초기 기본 설정내용을 그대로 사용하도록 하겠다) 이제 listener 을 가동시켜야 한다. oracle 계정으로 스위치 유저한다음에 lsnrctl 을 사용하면 리스너를 가동시킬수 있다.

[oracle@localhost admin]$ lsnrctl

LSNRCTL for Linux: Version 8.1.7.0.0 - Production on 30-OCT-2002 00:34:12

(c) Copyright 1998 Oracle Corporation.  All rights reserved.

Welcome to LSNRCTL, type "help" for information.

LSNRCTL> start
Starting /usr/u01/product/8.1.7/bin/tnslsnr: please wait...

TNSLSNR for Linux: Version 8.1.7.0.0 - Production
System parameter file is /usr/u01/product/8.1.7/network/admin/listener.ora
Log messages written to /usr/u01/product/8.1.7/network/log/listener.log
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=tcp)(HOST=localhost)(PORT=1521)))
Listening on: (DESCRIPTION=(ADDRESS=(PROTOCOL=ipc)(KEY=EXTPROC)))
...
...
The command completed successfully
				
LSNRCTL> 프롬프트 상에서 status 를 이용하면 현재 리스너의 상태를 확인할수 있으며, stop 를 이용해서 리스너를 중지 시킬수 있다.


2.3절. tnsnames (클라이언트측)

이제 클라이언트측 설정을 해야 한다. 당연히 클라이언트측 호스트에는 Oracle 클라이언트 제품군이 설치되어 있어야 한다(설치되어 있다고 가정하고 문서를 진행 하겠다).

tnsnames 는 간단히 생각하자면 클라이언트 어플리케이션이 오라클 서버에 접근하기 위해서 알아야될 서버측 정보를 담고 있는 데이타베이스라고 알고 있으면 된다.


2.3.1절. tnsnames 설정

$ORACLE_HOME/network/admin/tnsnames.ora 라는 파일이 바로 서버정보를 담고 있는 파일이다.

INST1_HTTP =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVER = SHARED)
      (SERVICE_NAME = oracle)
      (PRESENTATION = http://admin)
    )
  )

EXTPROC_CONNECTION_DATA =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
    )
    (CONNECT_DATA =
      (SID = PLSExtProc)
      (PRESENTATION = RO)
    )
  )

ORACLE =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = oracle)
    )
  )
				
역시 이해하는 데에는 별로 어려움이 없을것이다. 다른건 별로 신경쓸것 없고 마지막에 있는 ORACLE 정도만 알고 있으면 될것이다. 여기에 보면 접근할 서버의 정보들이 나와 있다. listener.ora 와 비교하면 쉽게 이해가 가능할 것이다. localhost 로 접근하며 1521 포트로 tcp 연결을 하고 oracle DB를 사용하겠다는 정보를 가지고 있다. 만약에 서버측에 zipcode 라는 DB 가 있고 zipcode 에 연결하기 위한 내용을 추가하고 싶다면 아래와 같이 추가시켜주면 될것이다.
ORACLE =
  (DESCRIPTION =
    (ADDRESS_LIST =
      (ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
    )
    (CONNECT_DATA =
      (SERVICE_NAME = zipcode)
    )
  )
				
물론 listener.ora 에도 여기에 알맞는 설정이 되어있어야 할것이다.


2.3.2절. 테스트

그럼 간단히 테스트를 해보도록 하자. 테스트는 sqlplus 라는 오라클에서 제공하는 클라이언트 프로그램을 이용할것이다.

 
[oracle@localhost admin]$ sqlplus system/manager@ORACLE

SQL*Plus: Release 8.1.7.0.0 - Production on Wed Oct 30 00:51:35 2002

(c) Copyright 2000 Oracle Corporation.  All rights reserved.


Connected to:
Oracle8i Enterprise Edition Release 8.1.7.0.1 - Production
With the Partitioning option
JServer Release 8.1.7.0.1 - Production

SQL> 
				
SQL> 프롬프트가 떨어진다면 listener 가 제대로 작동하며 해당 tnsnames 를 이용해서 연결을 성공했음을 의미한다.


2.4절. 데이타 베이스 준비하기

그럼 테스트를 위한 데이타베이스를 준비해 보도록 하자. 준비할 데이타 베이스는 우편번호이다. 자료실에서 다운로드 받을수 있다.

압축을 풀면 10개 정도의 파일이 생성될것인데, 오라클에서 곧바로 읽어들일수 있다. sqlplus 를 이용해서 oracle db 에 접근하도록 한다. 그다음 "@파일이름" 식으로 적재하면 된다.

  
SQL> @postcode.sql
Input truncated to 3 characters

Table created.

SQL> @postcode1.sql 
...
SQL> @postcod2.sql
			
이로써 테스트용 db 생성까지 모두 마쳤다. 적재하기가 귀찮다면 그냥 테스트용으로 파일 하나 분량 정도만 적재해도 관계는 없다.


3절. Pro *C/*C++ 소개

Pro *C(이하 proc) 는 일종의 프리컴파일러다. 즉 C코드에 오라클관리를 위해서 일상적으로 사용하는 SQL, PL/SQL 등을 결합시켜서 코딩된 프로그램을 C컴파일러(여기에서는 gcc)가 인식할수 있는 C 코드 파일로 변경시켜주는 일을 한다. 오라클에서는 proc 라는 프리컴파일러를 제공하고 있다.


3.1절. 왜 proc 를 사용하는가

아마도 1GL 이니 2GL 이니 하는 프로그래밍 언어 세대를 나타내는 말에 대해서 들어 보았을것이다. 보통 1세대 언어, 2세대 언어라는 식으로 불리는데, 이 분류에 따르면 C 언어는 3세대 언어(3GL)이다. 이에 반해 SQL(Structur query language) 언어는 4세대 언어로써, 3GL 언어가 절차식 언어인데 반해서, 4세대 언어는 좀더 자연어에 근접한 언어적 특성을 가진다.

이러한 4GL 언어가 가지는 자연어에 근접한 특성은 언어 사용을 직관적이고 쉽게 할수 있도록 만들어주지만, 절차지향 적인 업무를 처리하기에는 그리 적합하지가 않다. 그래서 많은 경우 C, C++, JAVA 등의 언어들과 결합해서 사용 하게 된다.

그런데 대게의 경우 이러한 3GL언어와 4GL 언어의 결합과정은 꽤나 성가신 작업이며, 많은 시간을 필요로 한다. SQL 은 별도로 하고, 거기에 덧붙여서 다양한 API 들을 새로 익혀야 하기 때문이다. 그나마 mysql, postgresql 과 같은 비교적 단순한(오라클에 비해서) DB의 경우 몇가지 API 만 익힘으로써 그리 어렵지 않게 프로그래밍 할수 있지만, 오라클의 경우 상당한 노력을 필요로 한다. 이러한 저수준에서 직접접근을 위해서 제공하는게 OCI(Oracle Call Interface) 라는 API 모음이다.

그래서 높더 높은 레벨에서 C 언어와 SQL 언어를 결합해서 프로그래밍 할수 있는 환경을 제공하고자 하는 목적에서 나온게 바로 proc 이다. proc 소쓰를 보면 알겠지만 복잡한 API 들 대신에 SQL 의 문장을 그대로 사용하고 있음을 알수 있다.

또한 proc 는 C 코드네에 PL/SQL 블럭을 직접 넣어서 코딩할수 있도록 되어 있다. PL/SQL 은 4GL 언어의 자연어적인 특성에 절차식 언어인 3GL 언어의 특징을 결합시킨 도구이다. PL/SQL 에 대한 내용은 자세히 다루지는 않을것이며, 필요할경우 약간씩 다루도록 하겠다. 어쨋든 proc 를 이요한 프로그래밍을 하려면 PL/SQL 에 어느정도 익숙해질 필요가 있다. PL/SQL 은 4GL 언어의 특성을 가지므로 C, JAVA 등에 비해서 매우 쉽게 익힐수 있다.


3.2절. proc 컴파일 과정

일단 프로그래머는 SQL 문이 포함되어 있는 코드를 작성한다. 보통이러한 코드는 확장자가 .pc 로 되어있다. 그러나 이러한 .pc 코드는 gcc 컴파일러가 컴파일 할수 없음으로 gcc 가 이해할수 있는 .c 코드로 변경시켜주는 "선행컴파일" 과정이 필요하다. 이 선행컴파일러거 .pc 파일을 .c 코드로 변경한 이후의 컴파일 과정은 기존 c 컴파일 과정과 완전히 동일하다.

     +--------------+
     | Proc Program | SQL 문을 포함
     | .pc          | 
     +--------------+
            ↓
     +--------------+
     | 오라클       | 
     | 선행컴파일러 | 
     | proc         |
     +--------------+
            ↓
     +--------------+
     | 해석된       | 기존의 SQL 문은 library 를 
     | .c 쏘쓰코드  | 직접 호출하는 문으로 변경됨 
     +--------------+
            ↓
     +--------------+
     | C 컴파일러   | 
     +--------------+
            ↓
     +--------------+
     | Object 파일  | 
     +--------------+
            ↓
     +--------------+
     | Linker       | 오라클 라이브러리가 링크됨 
     +--------------+
            ↓
     +--------------+
     | 실행파일     | 
     +--------------+

			


4절. 간단한 proc 프로그램 예제

다음은 zipcode 테이블에 총몇개의 자료가 들어있는지 알아오는 아주 간단한 프로그램이다.

예제 : zipcode.pc

 
#include <stdio.h>
#include <unistd.h>

/* SQLCA 를 선언한다 */
EXEC SQL INCLUDE SQLCA;

int main(int argc, char **argv)
{
    /* 선언부 */
    EXEC SQL BEGIN DECLARE SECTION;
            int count = 0;
            char userid[40]= "system/manager@ORACLE";
    EXEC SQL END DECLARE SECTION;

    /* DB 연결 */
    EXEC SQL CONNECT :userid;

    /* 에러 처리 */
    if (sqlca.sqlcode < 0)
    {
            printf("%s\n", sqlca.sqlerrm.sqlerrmc);
            EXEC SQL ROLLBACK WORK RELEASE;
            exit(0);
    }

    /* 쿼리 */ 
    EXEC SQL SELECT count(*) 
            INTO: count  
            FROM zipcode;

    /* 쿼리 결과에 대한 에러처리 */
    if (sqlca.sqlcode != 0) 
    {
            EXEC SQL COMMIT WORK RELEASE;
            return 0;
    }

    printf("우편주소 데이타 : %d 개\n", count);

    /* DB 연결 종료 */
    EXEC SQL COMMIT WORK RELEASE;
}
		
코드를 보면 알겠지만 뭐 복잡하게 이것 저것 인클루드 시켜줄 필요도 없고, SQL 문이 거의 그대로 쓰여서 이해하기도 매우 쉽다는 것을 알수 있을 것이다. 참고로 오라클 proc 쏘쓰파일에서의 주석은 /* */ 만 사용가능하다. // 을 썼다가는 오류가 발생한다.

이번 문서는 단지 이런식으로 프로그래밍이 가능하다라는 정도만 보여줄 것임으로 위의 코드의 설명은 생략하도록 하겠다. 나중에 자세히 다루도록 하겠다.


4.1절. 컴파일 하기

우선 zipcode.pc 파일을 proc 선행 컴파일러를 이용해서 zipcode.c 파일을 얻어낸다음 gcc를 이용해서 object 파일을 만들고 링크과정을 거쳐서 실행파일을 만들어야 한다. 다음은 이러한 일련의 과정이다.

[oracle@localhost proc]$ proc zipcode INCLUDE=include/ \ 
> include=/usr/u01/product/8.1.7/precomp/public/ \
> include=/usr/u01/product/8.1.7/rdbms/demo/ \
> include=/usr/u01/product/8.1.7/rdbms/public/ \
> include=/usr/u01/product/8.1.7/network/public/ \
> PARSE=NONE RELEASE_CURSOR=YES MODE=ANSI

Pro*C/C++: Release 8.1.7.0.0 - Production on Thu Oct 31 00:29:15 2002

(c) Copyright 2000 Oracle Corporation.  All rights reserved.

System default option values taken from: /usr/u01/product/8.1.7/precomp/admin/pcscfg.cfg

[oracle@localhost proc]$ gcc -c -o zipcode.o zipcode.c -I$ORACLE_HOME/precomp/public \ 
> -I$ORACLE_HOME/rdbms/demo -I$ORACLE_HOME/rdbms/public \
> -I$ORACLE_HOME/network/public

[oracle@localhost proc]$ gcc -o zipcode zipcode.o -L$ORACLE_HOME/lib -lclntsh
			
이 프로그램을 실행시키면 다음과 같은 결과값을 보여줄 것이다.
[oracle@localhost proc]$ ./zipcode 
우편주소 데이타 : 43476 개
			


4.2절. 컴파일 과정을 Makefile 로 관리하기

하지만 위의 방법대로 수동으로 코드를 컴파일 하는건 비 생산적인 방법이다. 그러므로 Makefile 을 만들어서 관리하도록 하자.

Makefile

TARGET          = zipcode

CC              = gcc
PROC            = proc
LIB             = -L$(ORACLE_HOME)/lib -lclntsh
MYINC           = include/
PROCINC         = include=$(ORACLE_HOME)/precomp/public/ include=$(ORACLE_HOME)/rdbms/demo/ \
	include=$(ORACLE_HOME)/rdbms/public/ \
	include=$(ORACLE_HOME)/network/public/ 
CINC            = -I$(ORACLE_HOME)/precomp/public/ -I$(ORACLE_HOME)/rdbms/demo/ \
	-I$(ORACLE_HOME)/rdbms/public/ -I$(ORACLE_HOME)/network/public/ 

ORA_OPT         = PARSE=NONE RELEASE_CURSOR=YES MODE=ANSI
CC_OPT          =

OBJECT          = zipcode.o
ORA_GARBAGE     = *.dcl *.cod *.cud *.lis

######## implicit rules
.SUFFIXES: .pc .c

.pc.c:
	$(PROC) $* INCLUDE=$(MYINC) $(PROCINC) $(ORA_OPT)
.c.o:
	$(CC) -c -o $*.o $*.c -I $(MYINC) $(CINC)

####### build rules

all:            $(TARGET)

$(TARGET):      $(OBJECT)
	$(CC) -o $(TARGET) $(OBJECT) $(LIB)

zipcode.c: zipcode.pc
zipcode.o: zipcode.c

clean:
	rm -f $(TARGET) $(OBJECT) $(ORA_GARBAGE)
			
이해하는데 특별히 어려움은 없을것이라고 생각된다. Makefile 에 대한 내용은 make 를 이용한 프로젝트 관리 (1)를 참고하도록 한다.


5절. 결론

이상 proc 프로그래밍을 위한 가장 기본적인 환경에 대해서 알아보았으며, 아주 간단한 예를 들어서 proc 프로그래밍을 맛보았다. 다음에는 좀더 자세한 proc 프로그래밍에 관한 내용을 다루도록 하겠다.




출처 - http://www.joinc.co.kr/modules/moniwiki/wiki.php/article/oracle_proc_programing

'DB > Oracle' 카테고리의 다른 글

뇌를 자극하는 오라클 프로그래밍 내용 정리  (0) 2012.02.29
Pro*C 개요  (0) 2012.02.24
Pro*C  (0) 2012.02.24
sqlplus 사용  (0) 2012.02.20
Oracle 관리 및 SQLPlus 정리  (0) 2012.02.20
Posted by linuxism
,

Pro*C

DB/Oracle 2012. 2. 24. 23:22

Pro*C (also known as Pro*C/C++) is an embedded SQL programming language used by Oracle Database database management systems. Pro*C uses either C or C++ as its host language. During compilation, the embedded SQL statements are interpreted by a precompiler and replaced by C or C++ function calls to their respective SQL library. The output from the Pro*C precompiler is standard C or C++ code that is then compiled by any one of several C or C++ compilers into an executable.

[edit]See also

[edit]External links


Pro*C Hello World Example

/* Hello World in Pro*C, the Oracle's embedded SQL environment */

#include 

EXEC SQL INCLUDE SQLCA;

int main() {
   char hello[15];
   char *user = "the_user";
   char *password = "the_password";
   char *sid = "the_sid";

   EXEC SQL CONNECT :user IDENTIFIED BY :password USING :sid;

   EXEC SQL
      SELECT 'Hello World' INTO :hello
      FROM DUAL;

   printf("%s\n", hello);

   EXEC SQL COMMIT RELEASE;

   return 0;
}


==========================================================================================

Pro*C ( 오라클 데이터베이스와 연동할 수 있는 C 프로그램 )

: Embedded SQL 프로그램이라고도 함.

 

: 내부 PL/SQL 을 통한 프로그램의 경우 오라클이라는 내부 울타리에서만 수행되는 특징이 큰 제약으로 작용한다. 이런 고민을 해결하기 위해서 대부분의 DBMS 벤더는 외부 C 프로그램과 결합할 수 있는 선행 컴파일러를 제공하고 있으며 오라클에서는 이를 Pro*C 라고 한다.

 

-> PL/SQL 과 같이 절차적 프로그래밍 이 가능한 프로그램 도구로서 PL/SQL 처럼 오라클 내부에서 수행되는 프로그램이 아니라 실행 가능한 외부 프로그램으로 작성이 되어 관련 작업을 수행 할 수 있게 해 주는 도구이다.

 

-> Pro*C 만으로는 실행 파일을 만들 수 없다. 따라서 Pro*C 는  C 프로그램을 컴파일할 수 있도록 x.C 파일을 생성해 준다(선행컴파일러). 이 x.C 는 통상적으로 컴파일 되고, 오라클 라이브러리와 결합되어 실행 파일이 만들어 진다.

 

< 프로그램 작성 방식 >

 

내장 SQL 방식

-> C 프로그램 내부에서 EXEC SQL 이라는 접두사 뒤에 SQL 문장을 직접 기술 하는 방식

-> 많이 사용 되는 방식임.

 

OCI 방식

-> OCI 라이브러리를 통해서 오라클 SQL 문장을 직접 호출하여 사용하는 방식.

 

두 방식의 차이점

 

내장SQL방식

- SQL 연산을 쉽고 명료하게 처리하기 위해 3GL  어플리케이션 개발

- 간결한 코드작성

- 컴파일 전에 소스 코드 선행 컴파일

- 선행 컴파일러를 별도로 구매

- ANSI 표준 준수

- 다중 행 질의만을 위해 명시적 커서 선언

- 선행 컴파일 시에 SQL 구문 확인

 

OCI 방식

- 데이터베이스를 최대한 제어하면서 3GL 어플리케이션 개발

- 길고 복잡한 코드 작성

- 선행 컴파일 단계 없이 코드 컴파일

- 오라클 데이터베이스와 함께 OCI 라이브러리 획득

- 독점 비 표준 절차적 호출 인터페이스 사용

- 모든 데이터베이스 연산을 처리하기 위한 명시적 커서 선언

- 실행 시간에 SQL 구문 확인



출처 -  http://blog.naver.com/sskkkll?Redirect=Log&logNo=120132622618 



'DB > Oracle' 카테고리의 다른 글

Pro*C 개요  (0) 2012.02.24
Pro*C 파헤치기  (0) 2012.02.24
sqlplus 사용  (0) 2012.02.20
Oracle 관리 및 SQLPlus 정리  (0) 2012.02.20
PL/SQL  (0) 2012.02.20
Posted by linuxism
,

헤더파일
헤더파일은 모듈화(modular) 프로그래밍과 관련이 있다.

일반적으로 소프트웨어 공학에서 이야기하는 모듈(module)이라는 것은 크게는 하나의 파일이 될 수도 있지만, 작게는 하나의 함수가 될 수도 있다. 

구현하고자 하는 프로그램 코드를 기능별로 적절히 나눠서 독립된 파일에 저장하여 관리한다. 이렇게 관리되는 파일들을 모듈이라 한다. 그리고 이러한 방식으로 프로그래밍하는 것을 모듈화(modular) 프로그래밍이라 한다.

/* file.c */
#include <stdio.h>

int i = 0;

int main(void) 
{
    i++;
    printf("%d \n", i);
    return 0;
}


file.c 파일을 file_1.c와 file_2.c로 분리

/* file_1.c */
int i = 0;


/* file_2.c */
#include <stdio.h>

int main(void) 
{
    i++;
    printf("%d \n", i);
    return 0;
}
    


extern 키워드
파일을 나눌 경우 main 함수에서 참조하는 변수 또는 함수가 외부에(다른 파일) 선언되어 있음을 컴파일러에게 알려줘야 하는데 이러한 경우에 변수나 함수 앞에 붙는 키워드가 extern 이다. 함수 원형 선언에서 extern 키워드는 생략 가능하다. 

/* file_2.c */
#include <stdio.h>

extern int i;

int main(void) 
{
    i++;
    printf("%d \n", i);
    return 0;
}


static 키워드
전역변수 앞에 static 선언을 하면 외부의 접근을 금지한다는 뜻이 된다(정확히 표현하면 변수의 접근 영역을 파일로 제한한다는 뜻이다). 즉, 다른 파일에서 아무리 extern 선언을 해도 접근이 불가능한 전역변수가 된다.


링크(link)에 대한 이해
나눠진 파일을 컴파일하면 각각 오브젝트 파일이 생성이 된다. 이 오브젝트 파일은 단지 기계어로 변환된 내용만을 지닐 뿐이지 이 자체가 실행 가능한 상태는 아니다. 즉, "extern int i"라는 선언은 main 함수 내에서 접근하고 있는 변수 i가 외부에 존재한다는 정보만을 담고 있는 것이다. 정작 변수 i가 외부 어디에 존재하는지는 모른다.

따라서 main 함수에서 접근하고 있는 i와 이 i를 선언하고 있는 다른 오브젝트 파일의 전역변수 i를 연결 시켜 줄 필요가 있다. 그래야 하나의 완성된 실행 파일을 생성할 수 있기 때문이다. 이처럼 최종적인 실행 파일의 생성을 위해서 접근하는 변수가 어디에 존재하는지, 호출하는 함수가 어디에 존재하는지 연결해 주는 작업을 가리켜 링크라 한다.



표준 헤더 파일
ANSI-C에서 표준으로 정의하고 있는 함수를 사용하기 위해 포함시킨 헤더 파일을 말한다. 대표적인 예가 stdio.h 이다. 즉, ANSI 표준에서 정의하고 있는 헤더 파일이 표준 헤더 파일이다.

#include <stdio.h>         -> 표준 헤더 파일 포함
#include "file_1.h"          -> 사용자 정의 헤더 파일 포함



헤더 파일 생성
"extern int i" 처럼 main 함수에서 선언해야 하는 외부 변수가 수 없이 많다면, 그리고 main 함수가 아닌 다른 외부 파일에서도 사용한다면 상당히 번거롭게 될 것이다. 
따라서 우리는 이러한 번거로운 일들을 편히 하기 위해서 헤더 파일이라는 것을 만든다.

/* file_1.c */
int i = 0;

/* file_1.h */
extern int i;

/* file_2.c */
#include <stdio.h>
#include "file_1.h"

int main(void) 
{
    i++;
    printf("%d \n", i);
    return 0;
}



출처 - 열혈강의 C 프로그래밍






1. 라이브러리와 헤더는 엄연히 다릅니다. 라이브러리는 기계어로 번역된 바이너리이며, 헤더는 컴파일러가 컴파일하기전.. 그러니까 프로그래머가 알아먹을 수 있고 c/c++의 문법에 맞게 작성되어있는 선언들의 집합입니다.

라이브러리를 사용하기 위해서는 해당 라이브러리의 헤더파일이 있어야합니다. 그래야지만 링커가 알아먹을수 있는 심볼네임을 컴파일러가 만들어내기 때문입니다.

컴파일러가 이런 헤더파일을 가지고 심볼네임을 만들어서 오브젝트 파일에 넣어주면 링커가 해당 심볼네임을 가지고 라이브러리를 뒤져서 링크를 하게 됩니다.

헤더가 여러개 모이는게 라이브러리가 아닙니다. 라이브러리는 컴파일된 바이너리이므로 소스파일의 컴파일된 산물인 오브젝트(리눅스의 경우에는 .o , 윈도우의 경우에는 .obj)파일을 여러개 모아놓은게 라이브러리입니다.

라이브러리의 확장자는 리눅스의 경우에는 .a, 윈도우의 경우에는 .lib입니다.

2. 제가 리눅스를 많이 안써봐서 말씀하신 위치 이외에 라이브러리와 헤더가 들어가는지는 모르겠습니다. (물론 나열하신 위치 말고도 다른 위치를 컴파일러 옵션으로 지정이 가능합니다.)
다만 나열하신 위치에 들어있는 파일들이 라이브러리와 헤더들입니다..

3. visual c보다는 visual c++이라고 하셔야 맞을거 같습니다.. 물론 6.0, .net 2003 .net 2003, .net2005과 같이 여러버전이 존재합니다.

4. 일반적으로 표준 c라이브러리는 대부분의 c컴파일러가 지원합니다. 표준 함수를 알고 계시면 대부분의 컴파일러에서 동일하게 소스를 바꾸지 않고 컴파일이 가능합니다.

5. 컴파일러와 라이브러리는 별개입니다. 컴파일러를 설치하면 들어있는 표준 c라이브러리도 사실 없어도 프로그램이 컴파일되는데는 문제가 없습니다. 대신 직접 모든걸 다 해줘야하는게 문제입니다. c언어의 시작 함수가 main이지만 실제로는 이 main함수를 호출하기전에 해주는 것이 많습니다. 그런걸 직접 일일이 만들어줘야하는 것이죠..

그리고 라이브러리는 c표준 라이브러리 뿐만 아니라 누구든지 라이브러리로 구성하면 그게 다 라이브러리입니다.


출처 -  http://kldp.org/node/84138 




11. 라이브러리와 헤더파일


원시 프로그램은 여러 파일로 나누어 각각 별도로 번역할 수 있는데 번역(compile)된 루틴들을 모아둔 파일을 라이브러리(library)라 한다. 프로그램에서 라이브러리 루틴을 사용하려면, 마치 함수가 사용자 프로그램에 정의되어 있는 것처럼 간단히 호출만 하면 된다. 라이브러리 함수는 번역된 형식으로 저장되어 있기 때문에 사용자 프로그램은 라이브러리 파일 또는 라이브러리 함수를 포함하는 파일과 링크(link)되어야 한다. 라이브러리를 다른 파일과 링크하면, 선언된 라이브러리 함수만이 실행파일에 포함되지만, 파일에 함수를 작성해 두고 번역하여 두 파일을 링크시키면, 불필요한 함수까지 코드로 첨가되기 때문에 라이브러리는 디스크 공간과 주 메모리를 절약하는데 필요하다.

main()함수에서 외부함수는 사용되기 전에 선언되어야 하기 때문에 만약 외부함수가 많거나 여러번 사용되려면, 사용 전에 매번 선언되어야 하고 선언이 정확해야 하기 때문에 번거러운 문제가 야기된다. 따라서 함수에 대한 선언을 외부파일에 하나로 통합시켜 두고 원시프로그램에 포함시키기 위하여 작성된 파일을 헤더파일(header file)이라 한다. 라이브러리의 대다수 루틴들은 함수정의 및 선언들을 필요로 하기 때문에 링크되기 전에 선처리기에 의하여 해당 헤더파일을 원시프로그램에 포함시켜야 한다.

   C의 실행시간 라이브러리에 있는 대부분의 루틴들은 함수이나, 어떤 루틴은 매크로로 구현되어 있다. 매크로는 기능상 함수와 같으나 문자열들은 프리프로세스 단계에서 코드로 치환하기 때문에 함수 호출시의 비용을 줄일 수 있고, 실행시간이 함수보다 빠르다. 그러나 매크로가 반복해서 호출될 경우에는 코드의 반복된 치환으로 인하여 프로그램의 크기가 확장되는 단점을 갖기도 한다.

 

■ 매크로와 함수의 근본적인 차이점

   1)  매크로의 매개변수를 여러 번 평가하면 부작용으로 잘못 평가될 수 있다.

   2)  매크로명은 함수처럼 주소에 의하여 평가되지 않기 때문에 사용자가 포인터를 요구하는 경우에는 매크로를 사용할 수 없다. 만약 사용자가 함수호출시에 매개변수로 매크로명을 사용하면 매크로에 의하여 계산된 값이 전달된다.

   3)  매크로는 함수가 아니기 때문에 선언될 수 없고, 매크로를 포인터로 참조할 수 없다. 그리고 매크로의 매개변수에 대해 자료형 검사가 없다. 그러나 인수의 갯수는 검사된다.

   4)  매크로로 정의된 라이브러리 루틴은 라이브러리의 헤더파일에 #define으로 정의된다. 따라서 라이브러리에 정의된 매크로를 사용하려면 사용자는 해당 헤더파일을 포함시켜야 한다.

 

■ 헤더파일에 서술된 내용

   다수의 실행시간 루틴은 별도로 매크로와 상수, 변수 그리고 자료형을 사용하기 때문에 번역될 프로그램 파일에 이들을 연결해야 한다. 헤더파일의 내용은 실행시간 루틴에 따라 다르나, 일반적으로 다음과 같은 내용들을 정의해 두고 있다.

   1) 헤더파일은 특정한 변수나 분명한 상수를 정의한다. 예를 들면 입출력에 필요한 버퍼의 크기 등 실행동안에 불변하는 자료를 정의해 둔다.

   2) 헤더파일은 특정한 자료형 내지 자료구조를 정의한다. 실행루틴이 매개변수나, 구조적 자료형을 반환값으로 갖는 경우에 이러한 자료형을 정의해 둔다. 예를 들면 스트림 입출력 연산자는 FILE형에 대한 포인터를 사용한다.

   3) 헤더파일은 함수의 정형이나 다른 언어의 함수를 실행시간 루틴에 사용할 때 이들을 사용자 프로그램에 포함시키고 라이브러리 루틴과 연결하기 위하여 선언된다.

   4) 헤더파일은 매크로를 정의한다.

   5) 헤더파일은 Directives를 사용한다.

       - #include

       - #define TRUE -1

       - #undef argument : argument의 정의를 취소한다.

       - #if - #else -

              #elif -

              #endif

       - #error <메시지> : 컴파일을 중단하고 <메시지>를 보여준다.

       - #line <number> <file>: 파일 <file>의 행번호 <number>로 점프

       - #if defined(<arg_1>)  #else : <arg_1>이 정의되어 있으면 뒷 부분을

               컴파일하고, 그렇지 않으면 #else 부분을 번역한다.

       - #if !defined(<arg_1>) else : <arg_1>이 정의되어 있지 않으면 뒷부분

               을 컴파일하고, 그렇지 않으면 #else 부분을 번역한다.

 

       ☞   #if defined(_header2)

   #error HEADER1.H and HEADER2.H cannot be used simultaneously.

   #else

   #define _header1

   #if defined(PI)

   #endif

   #define PI 3.14159

   #endif

 

   Directive로 서술된 내용을 사용자 프로그램에 포함시키려면, 그에 대한 헤더파일을 #include로 선언해야 한다. 

   ☞    #include <function.h>

main()

{    int  i, j, k;

}

 

/* function.c 원시 파일 */

int  increment(int a)

{     return (a+1);

}

 

/* 헤더파일 function.h */

int  increment(int);

 

■ 헤더파일의 종류

   헤더파일은 C 시스템의 서브 디렉토리인 INCLUDE에 있는데 헤더파일의 선언내용은 컴파일러마다 다를 수 있으나 일반적으로 아래와 같은 내용을 포함하고 있다.

 

   1)  <conio.h> : 입출력 포트와 콘졸(console)에 대한 모든 함수를 선언하고 있다.

   2)  <ctype.h> : 문자부류에 사용된 전역변수를 선언하고, 이에 대한 상수와 매크로를 정의한다. 예를 들면 islower(), toascii(), _tolower()와 같은 매크로와 _upper, _lower와 같은 상수를 정의하고, _ctype과 같은 전역변수를 선언한다.

   3)  <direct.h>:  chdir, getcwd, mkdir와 rmdir와 같이 디렉토리를 제어하는 함수를 포함하고 있다.

   4)  <dos.h> :  int86, int86x, intdos와 같이 MS-DOS 인터페이스 함수에 대한 매크로 정의, 함수선언, 형 정의를 포함하고 있다.

   5)  <errno.h> :  errno 변수의 값을 정하기 위하여 시스템 수준의 호출에서 사용되는 값을 정의한다.

   6)  <fcntl.h> :  파일이 텍스트모드 또는 이진모드로 해석되는지를 제어하고, 파일이 열리는 연산자의 형을 서술하기 위하여 호출되는 open과 fopen에서 사용되는 프래그(flag)를 정의한다.

   7)  <io.h> :  eof, open, tell, read, lseek, tell과 같이 저수준 입출력 함수와 파일처리에 필요한 함수를 선언하고 있다.

   8)  <malloc.h>: calloc, malloc, realloc과 같이 동적으로 메모리를 할당하는 함수를 선언하고 있다.

   9)  <math.h> : sqrt, sin, log10, pow, matherr와 같은 모든 수학루틴에 대한 함수를 선언하고 있다.

   10) <memory.h>: memcpy, memcmp, memset와 같이 버퍼 변경루틴에 대한 함수를 선언하고 있다.

   11) <process.h>: abort, exit, execle, system과 같이 모든 프로세스 제어함수를 선언하고 있다.

   12) <search.h> : bsearch, qsort와 같은 함수를 선언하고 있다.

   13) <signal.h> : signal과 같이 신호에 대한 값을 정의하고 있다.

   14) <stdio.h>  : fclose, fopen, gets, fread, scanf, printf, fprintf, fscanf와 같이 스트림 입출력에 대한 함수선언 및 매크로와  FILE과 같은 자료형과, EOF, NULL, BUFSIZ와 같은 상수를 정의하고 있다.

   15) <stdlib.h> : abs, atoi, itoa, rand, toupper, getenv와 같은 함수선언을 포함하고, errno와 같은 전역변수 선언하고 있다.

   16) <string.h> : strcat, strcpy, strcmp, strncmp와 같이 문자열 처리함수를 포함하고 있다.

 

   이밖에 운영 시스템과 C 언어의 유형에 따라서 여러 헤더파일이 있으며, SYS라는 서브 디렉토리에는 시스템 수준의 호출에 사용되는 함수, 매크로, 변수 및 상수들이 선언 또는 정의되어 있다.


출처 - http://stbiho.daegu.ac.kr/~minmild/c-lang/11.htm






'Development > C' 카테고리의 다른 글

c - 전처리문의 종류  (0) 2012.10.28
gcc 옵션 정리 - 자바 -D 옵션 의미  (0) 2012.03.23
C에서 정의된 FILE 구조체  (0) 2012.02.22
C 표준 라이브러리  (0) 2012.02.11
C언어 표준  (1) 2012.02.11
Posted by linuxism
,