동적 적재 라이브러리 단일 사용 (DL)

dlopen, dlsym, dlclose, dlerror

함수명 매개변수 반환값 변화
void dlopen (const char *filename, int flag) NULL (so 파일 존재하지 않거나 로딩 실패 한 경우)
NULL 아님 Shared object 참조 카운트 1 증가
void dlsym (void *handle, const char *symbol) NULL (symbol이 존재하지 않는 경우)
NULL 아님 (해당 symbol과 연관된 주소값 반환)
int dlclose (void* handle) 0 (정상적으로 close 됨)
그 외의 값 (에러 발생 dlerror를 통해 확인 필요) Shared object 참조 카운트 1 감소 (참조 카운트가 0이되면 메모리에서 삭제)
char* dlerror (void) 마지막 발생한 error 메시지 반환
에러 없는 경우 NULL

사칙연산 기능과 연산 결과를 출력하는 함수를 담은 라이브러리를 작성

해당 라이브러리를 main 프로그램에서 동적으로 적재하여 사용하는 예제

파일 구조

arith.hpp : 함수 선언을 담은 파일

arith_func1.cpp : 사칙 연산 함수 구현

libarith.so : 위 파일을 --shared 옵션을 통해 만든 공유 라이브러리 파일

main.cpp : libarith.so 공유 라이브러리 파일을 런타임 참조하도록 작성한 파일

// arith.hpp
#ifndef ARITH_HPP
#define ARITH_HPP

extern "C" {
    int add(int a, int b);
    int sub(int a, int b);
    int divv(int a, int b);
    int mul(int a, int b);
    void printall(int a, int s, int d, int m);
}

#endif

// arith_func1.cpp
#include "arith.hpp"

int add(int a, int b) {
    return a+b;
}

int sub(int a, int b) {
    return a-b;
}

// arith_func2.cpp
#include <stdio.h>
#include "arith.hpp"

int divv(int a, int b) {
    return a/b;
}

int mul(int a, int b) {
    return a*b;
}

void printall(int a, int s, int d, int m) {
    printf("Add: %d, sub: %d, Div: %d, Mul: %d\\n", a, s, d, m);
}

// main.cpp
#include <iostream>
#include <dlfcn.h>

using namespace std;

int main (int argc, char** argv) {
    int a, b;

    cout << "Input the Number (a/b) : ";
    cin >> a >> b;

    cout << "C++ dlopen demo running~~~~ \\n\\n\\n";

    cout << "Opening libarith.so.....\\n\\n";
    void* handle = dlopen("./libarith.so", RTLD_NOW); 
    // handle을 통해 라이브러리 파일 위치의 주소값을 넘겨 받음.
    // RTLD_NOW는 dlopen() 함수 호출과 동시에 load
    if(handle==0) {
        cerr << "Cannot open library : " << dlerror() << endl;
        return 1;
    }

    cout << "Loading symbol arith.... \\n\\n";
    typedef int (*add_t)(int, int);
    typedef int (*sub_t)(int ,int);
    typedef int (*divv_t)(int ,int);
    typedef int (*mul_t)(int, int);
    typedef void (*printall_t)(int, int, int, int);

    add_t add = (add_t) dlsym(handle, "add");
    sub_t sub = (sub_t) dlsym(handle, "sub");
    divv_t divv = (divv_t) dlsym(handle, "divv");
    mul_t mul = (mul_t) dlsym(handle, "mul");

    printall_t printall = (printall_t) dlsym(handle, "printall");
    
    if(printall == 0) {
        cerr << "Cannot load symbol 'arith' : " << dlerror() << endl;
        dlclose(handle);
        return 1;
    }

    cout << " Calling arith..\\n\\n";
    printall(add(a, b), sub(a, b), divv(a, b), mul(a, b));

    cout << "Closing library...\\n\\n";
    dlclose(handle);

    return 0;
}

Makefile

arith_func1.o: arith.hpp arith_func1.cpp
		g++ -c arith_func1.cpp -fPIC

arith_func2.o: arith.hpp arith_func2.cpp
		g++ -c arith_func2.cpp -fPIC

libarith.so: arith.hpp arith_func1.o arith_func2.o
		g++ -shared -o libarith.so arith_func1.o arith_func2.o

main: arith.hpp main.cpp libarith.so
		g++ -o main main.cpp -ldl

all : main

clean : 
		rm -f arith_func1.o arith_func2.o libarith.so main