2015년 8월 18일 화요일

C 언어 - 표준 API

API (Application Programming Interface)


API 란 특정 기능을 지원하는 함수나 자료구조들의 모음이다.
API 를 사용하는 입장에서는 헤더 파일과 라이브러리 파일들을 위치를 정하고 컴파일러에게 해당 파일들의 위치를 알려주면 미리 구현된 함수 및 자료구조를 사용할 수 있다.

표준 API 란 일반적으로 프로그램을 개발하는데 있어 기초적으로 필요로 하는 API 이다.
표준 API 는 컴파일러에게 헤더 파일과 라이브러리 파일 위치를 알려주지 않아도 컴파일러에 의해 자동으로 로드 된다.

stdio


stdio.h 에는 io (input/output) 에 관한 함수들이 제공된다.

printf() 함수는 이미 사용해 보았다.

printf 함수의 선언문은 이렇다.
int printf ( const char * format, ... );

... 부분은 지금까지 이야기 하지 않았지만 유효한 C 언어 문법이다.



표준 API 목록과 자세한 사용법은 아래 사이트에 아주 잘 정리 되어 있다.




문자열 출력, 입력, 문자열 처리, 파일 처리, 시간 처리 등의 API 들이 이미 표준으로 제공되고 있다.

표준 API 를 사용하는데 주저할 필요는 없다.
표준 API 로만 이뤄진 소스 코드는 어느 플랫폼에서건 컴파일되고 대부분 실행 결과도 같을 것이다.

표준 API 에 대해서는 사용법만 제대로 숙지하면 된다.

표준 라이브러리


C 언어 표준 API 들은 라이브러리 파일 형태로 저장이 되어 있다.

다만 컴파일러가 이러한 라이브러리 들을 기본적으로 로드하고 있기 때문에 개발자들이 신경쓰지 않아도 될 뿐이다.

표준 라이브러리를 찾아서

라이브러리 위치는 플랫폼마다 컴파일러마다 달라 진다.

리눅스 gcc 를 기준으로 설명하겠다.

$ gcc -xc -E -v -
Using built-in specs.
COLLECT_GCC=/usr/bin/gcc
Target: i686-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info --with-bugurl=http://bugzilla.redhat.com/bugzilla --enable-bootstrap --enable-shared --enable-threads=posix --enable-checking=release --disable-build-with-cxx --disable-build-poststage1-with-cxx --with-system-zlib --enable-__cxa_atexit --disable-libunwind-exceptions --enable-gnu-unique-object --enable-linker-build-id --with-linker-hash-style=gnu --enable-languages=c,c++,objc,obj-c++,java,fortran,ada,go,lto --enable-plugin --enable-initfini-array --enable-java-awt=gtk --disable-dssi --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-1.5.0.0/jre --enable-libgcj-multifile --enable-java-maintainer-mode --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --disable-libjava-multilib --with-ppl --with-cloog --with-tune=generic --with-arch=i686 --build=i686-redhat-linux
Thread model: posix
gcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)
COLLECT_GCC_OPTIONS='-E' '-v' '-mtune=generic' '-march=i686'
 /usr/libexec/gcc/i686-redhat-linux/4.7.2/cc1 -E -quiet -v - -mtune=generic -march=i686
ignoring nonexistent directory "/usr/lib/gcc/i686-redhat-linux/4.7.2/include-fixed"
ignoring nonexistent directory "/usr/lib/gcc/i686-redhat-linux/4.7.2/../../../../i686-redhat-linux/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/i686-redhat-linux/4.7.2/include
 /usr/local/include
 /usr/include

End of search list.


$ gcc -xc -E -v - 명령을 통해 표준 라이브러리 위치를 확인할 수 있다.

  • /usr/lib/gcc/i686-redhat-linux/4.7.2/ 에는 libgcc.a 나 libstdc++.a 등의 .a 또는 .so  확장자를 갖는 라이브러리 파일들이 있다.
  • /usr/lib/gcc/i686-redhat-linux/4.7.2/include 에는 헤더 파일들이 있다.
gcc 컴파일러 옵션을 이용해 라이브러리 파일을 컴파일 할 수 있고 .so 또는 .a 형태의 라이브러리 파일과 헤더 파일을 배포하여 다른 프로젝트에서 사용하도록 할 수 있다.

동적 라이브러리와 정적 라이브러리


동적 라이브러리는 .so 확장자를 갖고 정적 라이브러리는 .a 확장자를 갖는다.
둘의 가장 큰 차이는 프로그램 실행에 있다.

  • 동적 라이브러리는 프로그램 실행시에도 필요하다.
  • 정적 라이브러리는 컴파일 단계에서 프로그램에 녹아들기 때문에 실행시 필요 없어진다.

libmyutil.so 라는 동적 라이브러리를 필요로 하는 myprogram 실행 파일을 컴파일 했다면 myprogram 실행시에도 libmyutil.so 파일이 필요하다.

만약 libmyutil.a 라는 정적 라이브러리를 필요로 하는 myprogram 실행 파일을 컴파일했다면 이미 myprogram 에 .a 내용이 포함되었기 때문에 실행시에는 libmyutil.a 파일이 더 이상 필요없다.

unix/linux 라이브러리 파일명 규칙


lib 로 시작하고 .so 확장자를 갖는다.
컴파일 옵션으로 입력할 때는 lib 와 .so 부분은 제거한다.

예) libmyutil.so 라이브러리 파일이 있다면
$ gcc -o hello main.c -lmyutil

-l 은 라이브러리 파일을 로드하는 옵션이다.

댓글 없음:

댓글 쓰기