静的ライブラリと共有ライブラリの整理 - その2 -

概要

C++ における静的ライブラリと共有ライブラリの作成・使用方法を整理

ライブラリにするコード(サンプル[前回と同じ])

  • ヘッダーファイル: hoge.h
//hoge.h
#ifndef _HH_HOGE_
#define _HH_HOGE_

//extern "C" がないと関数名が変更されるのでリンクできなくなる
extern "C" void test(void);

#endif
  • ライブラリにする関数: hoge.cpp
//hoge.cpp
#include "hoge.h"
#include <iostream>

void test(void){
  std::cout << "hoge.cpp: test" << std::endl;
}

静的ライブラリ

静的ライブラリの作成方法
# オブジェクトファイルを作成する
$ g++-mp-4.8 hoge.cpp -c

# 静的ライブラリを作成
$ ar r libhoge.a hoge.o

# オブジェクトファイルがあるか確認する
$ ar t libhoge.a 
__.SYMDEF SORTED
hoge.o
静的ライブラリの使用方法
//main.cpp
#include "hoge.h"

int main(void){

  test();

  return 0;
}
コンパイル方法と実行結果
$ g++-mp-4.8 main.cpp -L ./ -l hoge 
$ ./a.out
hoge.cpp: test

共有ライブラリ

共有ライブラリの作成方法
# コンパイルで libhoge.so を作成する
$ g++-mp-4.8 -shared -fPIC hoge.cpp -o libhoge.so

# libhoge.so に test 関数があるか確認
$ nm libhoge.so
0000000000000ecb t __GLOBAL__sub_I_hoge.cpp
0000000000000e83 t __Z41__static_initialization_and_destruction_0ii
                 U __ZNSolsEPFRSoS_E
                 U __ZNSt8ios_base4InitC1Ev
                 U __ZNSt8ios_base4InitD1Ev
                 U __ZSt4cout
                 U __ZSt4endlIcSt11char_traitsIcEERSt13basic_ostreamIT_T0_ES6_
0000000000001050 s __ZStL8__ioinit
                 U __ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc
                 U ___cxa_atexit
0000000000000e55 T _test
                 U dyld_stub_binder
共有ライブラリの使用方法
//main.cpp
#include <iostream>
#include <functional>
#include <dlfcn.h>

using hoge_test = void (*)(void);

int main(void){
  void* handle = NULL;

  do{
    //libhoge.so をオープン
    handle = dlopen("./libhoge.so", RTLD_LAZY);
    if(handle == NULL){
      std::cerr << "error: dlopen(" << dlerror() << ")" << std::endl; 
      break;
    }
    
    //関数ポインタに test を格納
    auto func = (hoge_test)dlsym(handle, "test");
    if(func == NULL){
      std::cerr << "error: dlopen(" << dlerror() << ")" << std::endl; 
      break;
    }
    
    //test を呼ぶ
    func();
  } while(0);

  //handle をクローズ
  if(handle != NULL){
    if(dlclose(handle) != 0){
      std::cerr << "error: dlopen(" << dlerror() << ")" << std::endl; 
      return -3;
    }
  }

  return 0;
}
コンパイル方法と実行結果
$ g++-mp-4.8 main.cpp -ldl -std=c++11
$ ./a.out
hoge.c: test