C++のプログラムから共有ライブラリを呼び出す方法(macOS編)

Windows編の続報です。

macOSになると、タイトルがやや不正確になってしまいます。WindowsやLinuxでは実行時のリンクとプログラム中での明示的なリンクはあまり区別されませんが、macOSでは厳密に区別されます。

共有ライブラリ(Dynamic Linking)とダイナミックライブラリ(Dynamic Loading)を使い分けないとならないのが、macOSですね。Linuxはどちらも拡張子は.soですが、macOSの場合は、前者は.dylibで、後者が.bundleのようです。ダイナミックライブラリの拡張子は.bundleが推奨されているようですけど、しばしばLinuxを意識する場合などには.soがつけられるようです。

参考サイト

暗黙的リンク

Command line toolsは入れてあるものと仮定しております。もしg++が動かないようでしたら、「macOS command line tools」くらいで検索してインストールしてください(遥か昔に入れていたので入れ方忘れました…)。手元のg++は「Apple LLVM version 8.1.0 (clang-802.0.42)」だそうです。

呼ばれる共有ライブラリのプログラム側は以下のとおり。ファイル名はshared.ccとして

#include <iostream>
void hoge() 
{
    std::cout << "Hello Hoge!\n";
}

実に単純です。ヘッダファイル(shared.h)も一応載せておきます。一行だけです。

void hoge();

以下のようにコンパイルします。

g++ -dynamiclib -o shared.dylib shared.cc

呼ぶ側(tmp.cc)も簡単です。今回はエラー処理をさぼります(笑)。

#include "shared.h"

int main()
{
  hoge();
  return 0;
}

コンパイルは以下で行います。

g++ tmp.cc -lm shared.dylib

あとは実行するのみです。

./a.out

と実行すれば、Hello Hoge!と出力されると思います。

明示的リンク

暗黙的リンクとかなり似ている部分もありますが、異なる点を列挙します。まず、C++で書く場合には名前修飾への対応が必要なこと、あとは呼び出し側で関数のポインタの取得が必要なことです。以下、呼ばれる共有ライブラリ側のプログラムです。ファイル名は上と同様にshared.ccです。今回はヘッダファイルはいりません。

#include <iostream>

extern "C" void hoge()
{ 
  std::cout << "Hello Hoge!\n";
}

ここでextern “C”を忘れると呼び出し側で関数ポインタが見つからずに呼び出せません(名前修飾後の関数名を調べるという方法もありますが…)。コンパイルは以下のとおりです。

g++ -std=c++11 -bundle -o shared.bundle shared.cc

後でusingを使いたいのでこちら側もC++11を指定していること、bundleオプションの指定、あとはファイル名をshared.bundleに指定しております。

次に呼び出し側のプログラム(tmp.cc)です。

#include <dlfcn.h>
using HOGE_FUNCTION = void (*)(void);

int main()
{
  void *ptrHandle = dlopen("shared.bundle", RTLD_LAZY);
  HOGE_FUNCTION ptrDllFunc = (void (*)(void))dlsym(ptrHandle, "hoge");
  ptrDllFunc();
}

コンパイルは以下のように行います。

g++ -std=c++11 tmp.cc

あとは今まで通りに実行ができるはずです。

./a.out

Welcome to hoge world!

Linux版に続きます。

コメント

タイトルとURLをコピーしました