■ 정적 라이브러리 

정적 라이브러리는 컴파일 타임에 프로그램에 직접 연결됩니다.

정적 라이브러리를 사용하는 프로그램을 컴파일 시 정적 라이브러리 안의 모든 함수들이 실행 파일의 일부가 됩니다.

정적 라이브러리는 이진 파일의 전체 크기를 증가 시키지만 사용중인 라이브러리의 사본을 가지고 다닐 필요는 없습니다.

코드가 컴파일 타임에 연결되므로 추가로 런타임에 로드할 필요가 없습니다. 따라서 코드는 간단합니다.

 

■ 동적 라이브러리 

동적 라이브러리는 라이브러리를 사용하는 각 프로그램에서 복제되는 코드의 양을 줄여 바이너리를 작게 유지합니다.

프로그램의 런타임 시에 메모리에 로드되는 구조입니다.

동적 라이브러리를 사용하는 프로그램을 컴파일하면, 라이브러리 자체는 실행파일에 포함되지 않고 분리된 상태로 존재합니다.

 

■ 동적 라이브러리 동적 로드

QLibrary Class에 대한 정의 입니다. "The QLibrary class loads shared libraries at runtime."

동적 라이브러리를 동적으로 로드한다는 말이 낯설게 느껴지실 수 있습니다. 동적 라이브러리는 위에서 말했다시피 런타임 시에 메모리에 로드됩니다.

동적 라이브러리의 동적 로드가 필요한 경우에 대해 설명드리겠습니다.

 

프로그램 실행 도중에는 동적 라이브러리가 이미 메모리에 로드되어 있겠지만,

동적 라이브러리의 함수나 코드가 변경되어 현재 실행되고 있는 프로그램에 변경한 동적 라이브러리를 적용하고 싶은 경우가 있습니다.

프로그램을 종료한 후 재실행 시에는 변경된 동적 라이브러리가 로드되므로 다시 사용이 가능합니다.

 

하지만 Qt에서 제공하는 QLibrary Class를 사용하면 실행 중인 프로그램을 종료하지 않고,

기존에 로드되어 있던 동적 라이브러리를 제거하고 새로운 동적 라이브러리를 로드하여 사용할 수 있습니다.

런타임 시에 조금 더 유동적이고 유연한 프로그램을 만들 수 있는 Class입니다. 

 

■ 예제 코드

간단하게 1~10 까지 출력하는 testlib.cpp 파일을 빌드하여 /home/dynamic-library 폴더에 libtest_lib.so 라는 동적 라이브러리를 먼저 만들었습니다. 이제 동적 라이브러리를 프로그램 실행 중 원하는 Sequence에 load 할 수 있도록 QLibrary Class를 사용하여 프로그램에 로드하는 과정입니다.

 

제가 18번 째 줄에 if(g_testLibrary.isLoaded() == true)를 사용한 이유는 현재 프로그램은 라이브러리 접근 후에 프로그램에 종료되어서 의미가 없는 코드지만, QLibrary_Test() 함수가 쓰레드에서 상황에 따라 호출되는 함수라면 그 시점에 로드되어 있는 동적 라이브러리를 unload() 후 새로운 동적라이브러리를 load()하기 위함입니다.

 

24번 째 줄 이후부터는 함수 포인터를 사용하여 동적 라이브러리의 TEST_FUNC() 함수에 접근하였습니다.

아래와 같이 QLibrary Class를 사용하면 런타임 도중에도 프로그램에 변경된 동적 라이브러리를 적용할 수 있습니다.

 

// Main Loop

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// main.cpp
#include <QCoreApplication>
#include <QLibrary>
#include <stdio.h>
 
void QLibrary_Test();
 
int main(int argc, char *argv[])
{
    QLibrary_Test();
}
 
void QLibrary_Test()
{
    QLibrary g_testLibrary;
    g_testLibrary.setFileName("/home/dynamic-library/libtest_lib.so");
 
    if(g_testLibrary.isLoaded() == true)
         g_testLibrary.unload();
 
    if((g_testLibrary.load()) == false)
        printf("Test Library Load Error\n");
 
    typedef void (*p_libFunc)(void);
    p_libFunc libraryExe = NULL;
 
    libraryExe = (p_libFunc)g_testLibrary.resolve("TEST_FUNC");
 
    if(libraryExe)
            libraryExe();
 
}

 

// Dynamic Library 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// testlib.h
#ifndef TESTLIB_H
#define TESTLIB_H
 
#include <stdio.h>
 
extern "C" void TEST_FUNC();
 
#endif
 
 
// testlib.cpp
#include "testlib.h"
 
void TEST_FUNC()
{
    printf("TEST_FUNC Start\n");
    for(int i = 0; i < 10; i++)
        printf("%d ", i);
 
    printf("\nTEST_FUNC End\n");
}

 

// Result Image