AndroidやiOSではライブラリを作ることができます。例えばAndroidではAndroidNDKを使用してC++のソースから.soファイルを作成します。(NDKの使用方法)

NDKでライブラリを作る場合:

コンパイル方法
(1)jniフォルダにC++ソースとmakeファイルを置く
(2)ndk-buildコマンドを実行
(3)libsフォルダに.soが出来る

インタフェース用の.javaを作成
(1)System.loadLibrary("library_name");と記述
(2)C++で記述したものと同じ引数を持つ関数をnative指定で記述


NDKで作ったライブラリを使う場合:

.soと.javaをプロジェクトのlibsフォルダとsrcフォルダにコピー
javaの関数を呼ぶとJava_*というC++の関数が呼ばれる


また、iOSの場合はXcodeの”プロジェクトの新規作成”からStaticLibraryを選択することでスタティックライブラリのプロジェクトを作成することができます。このプロジェクトでコンパイルするとスタティックライブラリである.aファイルが作成されます。ただし、iOSはシミュレータ用にはi386命令、実機用にはarm命令でコンパイルする必要があります。そこで、ビルドターゲットをプロジェクト内で複製し、シミュレータ用とARM用にそれぞれビルド、Lipoで結合してユニバーサルバイナリにします。


lipo -create "DerivedData/test/Build/Products/Release-iphoneos-iphone/test.a" "DerivedData/test/Build/Products/Release-iphonesimulator-simulater/test.a" -output "test.a"


スタティックライブラリを使う場合は、作成したユニバーサルバイナリのtest.aとインタフェースを記述した.hをプロジェクトに追加すればよいです。

しかし、このままだと、Android/iOS共に、関数名や構造体名がだだ漏れになります。試しに.soや.aをテキストエディタで開いてみると、関数名が含まれていることが分かります。このようなライブラリをそのまま配布すると、知られたくない設計情報を解析することが可能になってしまいます。そこで、このような不要なシンボルをエクスポートしない方法を考えます。

Androidの場合は比較的簡単です。gccのビルドオプションに-fvisibility=hiddenを付けると、不要なシンボルはエクスポートされなくなります。エクスポートしたい関数にだけ

 __attribute__((visibility("default")))

を付けます。

 __attribute__((visibility("default"))) JNIEXPORT jint JNICALL Java_abars_test_CreateInstance(JNIEnv *env, jclass obj, jstring filename)

みたいな感じです。

ここまではいいんですが、iOSではこのオプションが使えません。というのも.aはオブジェクトファイルを結合しただけの形式だからです。従って、リンク時に有効な-fvisibilityは無効で、有効な解決策はありません。単純なライブラリであれば、無名名前空間に隠したい関数を全て入れてしまえばよいですが、テンプレートを使っているとうまくいきません。

ということで、結論としてはiOSではシンボルを隠せません。妥当な解決策としては、適当なスクリプトをperlとかで書いて、関数名とクラス名を正規表現で列挙し、ClassNo1とかfunc_no1とか適当なものに置換するぐらいです。

aa3


気合で置換するとこんな感じになります。将来的にはiOSでダイナミックリンクライブラリをサポートして欲しいですね。