메뉴 건너뛰기


Developer > Open Source

APR 4장. 동적 객체 다루기

2013.11.12 22:05

푸우 조회 수:6740

APR에서는 동적 객체(Dynamic Object)를 다루는 라이브러리를 포함하고 있습니다.
동적 객체라고 하면 뭘 말하는지 잘 모르시겠죠?
여기서 말하는 동적 객체란 Windows의 경우 .dll(Dynamic Linked Library), Unix, Linux의 경우 .so(Shared Object)를 이야기 하며 APR에서 APR_POOL환경하에서 이들 동적 라이브러리들을 읽어 들여 실행할 수 있는 함수를 제공한다는 이야기 입니다.
 
1) 동적 객체 다루는 함수 (Dynamic Object Handling)
 
동적 객체를 다루는 방법은 OS마다 조금씩 다릅니다.
하지만 개념은 모두 같습니다.
우선 .dll이나 .so파일을 로드하고 거기에서 사용하고자 하는 함수의 포인터를 얻어 옵니다.
얻어온 함수를 사용한 후 더 이상 사용하지 않을 경우 로드한 파일을 언로드 시키면 됩니다.
이와 관련된 APR 함수는 다음과 같은 것들이 있습니다.
 
apr_status_t apr_dso_load(apr_dso_handle_t **res_handle, const char *path, apr_pool_t *ctx)
apr_status_t apr_dso_unload(apr_dso_handle_t *handle)
apr_status_t apr_dso_sym(apr_dso_handle_sym_t *ressym, apr_dso_handle_t *handle, const char *symname)
const char *apr_dso_error(apr_dso_handle_t *dso, char *buf, apr_size_t bufsize)
 
위에서 부터 각각의 함수를 설명한다면 apr_dso_load()함수는 .dll, .so파일을 로드하기 위한 함수 입니다. apr_dso_unload()함수는 apr_dso_load()함수에 의해 로드한 객체를 언로드 시키는 함수 입니다.
apr_dso_sym()함수는 로드된 객체로 부터 필요한 함수 포인터를 얻어 오는 함수 입니다.
apr_dso_error()함수는 apr_dso_load()함수에서 에러가 발생한 경우 그 에러의 원인을 메시지로 알아보기 위한 함수 입니다.
 
#include "apr_pools.h" #include "apr_dso.h" int main(int argc, char *argv[]) { apr_status_t s; apr_pool_t *p=NULL; apr_dso_handle_t *res_handle; unsigned char buf[1024]; int(*MBox)(HWND, LPCSTR, LPCSTR, UINT); s=apr_initialize(); if(s==APR_SUCCESS){ s=apr_pool_create(&p, NULL); if(s==APR_SUCCESS){ s=apr_dso_load(&res_handle, "C:\\windows\\system32\\USER32.dll", p); if(s==APR_SUCCESS){ s=apr_dso_sym((apr_dso_handle_sym_t*)&MBox, res_handle, "MessageBoxA"); if(s==APR_SUCCESS){ MBox(NULL, "ABC", "DEF", 0L); }else{ fprintf(stderr, "얻어고자 하는 함수를 제공하지 않습니다.\n"); } apr_dso_unload (res_handle); }else{ fprintf(stderr, "Error: %s\n", apr_dso_error(res_handle, buf, 1024)); } } apr_pool_destroy(p); } apr_terminate(); return 0; }

위의 예제는 APR라이브러리를 이용하여 Windows의 USER32.dll파일을 열어 거기에서 제공하는 MessageBoxA()함수를 사용하여 메시지 상자를 띄우는 예제입니다.
 
참고로 위의 코드를 컴파일 한 후 실행하면 메시지 상자가 나타나고 확인을 누르면 "The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention."이라는 에러 메시지를 만나게 될 것 입니다. 이는 함수의 호출 형태가 USER32.dll파일과 맞지 않아 생기는 현상으로 이를 없앨려면 VC 프로젝트의 설정 대화 상자 =>  C/C++ 탭 => Category에 Code Generation을 설정하신후, Calling Convention의 값을 stdcall로 맞춰주고 다시 컴파일 후 실행하면 에러가 발생하지 않게 됩니다.
 
혹시 위의 예제에서 int(*MBox)(HWND, LPCSTR, LPCSTR, UINT); 구문이 이해가 안가시나요?
이는 함수 포인터를 정의하는 것입니다. 이부분을 설명하는 것은 지금 쓰고 있는 강좌의 범위를 벗어나는 이야기 이므로 여러분 스스로 공부하세요.
C언어의 포인터에 대해 고급 프로그램에 속하므로 그 부분을 찾아서 공부하세요.
 
 
Creative Commons License
Creative Commons License이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-동일조건변경허락 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
Copyright 조희창(Nicholas Jo). Some rights reserved. http://bbs.nicklib.com