17
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Xamarin.AndroidでNDKを利用する

Last updated at Posted at 2015-07-17

JXUG Conference 大阪で発表したXamarin.Android+NDKの、デモ部分の解説記事です。

スライドはこちら。
「Xamarin.Androidでネイティブコードと仲良しになる方法」
http://www.slideshare.net/hIDDENxv/xamarinandroidndk

Xamarin.AndroidでC/C++記述したネイティブコードをプロジェクトに含めて利用するための、シンプルな手順を解説します。
前提は、Xamarin、Android SDK、Android NDK環境が整っていること。
Mac+Xamarin Studioで解説しているので、他の環境の場合は適宜読み替えていただければと。

アジェンダはこちら。
1.NDKビルド環境を整える
2.ビルドしてできたlibsフォルダ以下を、プロジェクトに追加する
3.C#からコールする
4.ビルドターゲットを追加する

##1.NDKビルド環境を整える
まずはAndroidアプリプロジェクトを作成します。
そして、ndk-buildからみて通常のAndroidアプリプロジェクトにみえるように、プロジェクトフォルダ以下の構成を整えます。

ひとつめ。プロジェクトにproject.propertiesファイルを追加。

project.properties
target=android-19

ふたつめ、プロジェクトにjniフォルダを作成し、mkファイルとソースを追加。

Android.mk
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE    := NativeTest
LOCAL_SRC_FILES := Native.cpp

include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all
Native.cpp
extern "C"
{
    int add( int a, int b );
}

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

ここまでできたら、ターミナルを開いてビルドしてみます。
プロジェクトフォルダまで移動して、ndk-buildを実行。下記のようなメッセージが表示されれば成功です。

Compile++ thumb  : NativeTest <= Native.cpp
SharedLibrary  : libNativeTest.so
Install        : libNativeTest.so => libs/armeabi/libNativeTest.so
Compile++ thumb  : NativeTest <= Native.cpp
SharedLibrary  : libNativeTest.so
Install        : libNativeTest.so => libs/armeabi-v7a/libNativeTest.so
Compile++ mips   : NativeTest <= Native.cpp
SharedLibrary  : libNativeTest.so
Install        : libNativeTest.so => libs/mips/libNativeTest.so
Compile++ x86    : NativeTest <= Native.cpp
SharedLibrary  : libNativeTest.so
Install        : libNativeTest.so => libs/x86/libNativeTest.so

##2.ビルドしてできたlibsフォルダ以下を、プロジェクトに追加する
NDKビルドに成功すると、プロジェクトフォルダ下にlibsフォルダが作成されているはず。
libsフォルダには、各プラットフォーム向けのライブラリファイルができているので、必要なぶんだけプロジェクトに追加し、ビルドアクションを「AndroidNativeLibrary」に設定します。
スクリーンショット 2015-07-17 12.13.39.png

##3.C#からコールする
このネイティブバイナリをC#コードからコールするには、C#でWindowsアプリを書いていたことのある人にはおなじみの、DllImport属性を使います。

今回はテンプレートで生成されたMainActivityに追記してみます。

MainActivity.cs
[DllImport("NativeTest")]
public static extern int add(int a, int b);

そのままボタンタッチ時の処理を書き換えて、ネイティブコード実行の確認ができるようにします。

MainActivity.cs
button.Click += delegate
{
    var rand = new Random();
    var a = rand.Next(100);
    var b = rand.Next(100);
    button.Text = String.Format("{0} + {1} = {2}", a, b, add(a, b));
};

実行するとこのように。無事コールされているのが確認できます。
run.png

##4.ビルドターゲットを追加する
ここまでネイティブコードのビルドにはターミナルからndk-buildを実行していましたが、これでは不便。
そこでプロジェクトファイル(csproj)に下記のような<Target>タグを追加します。

*.csproj
<Project>
  <Target Name="BeforeBuild">
    <Exec Command="$(AndroidNdkDirectory)/ndk-build" />
  </Target>
</Project>

(いただいたコメントにより、追記修正しました)
ここまでネイティブコードのビルドにはターミナルからndk-buildを実行していましたが、これでは不便。
というわけで、プロジェクト設定のカスタムコマンドという機能を使って、プロジェクトビルド時にNDKビルドも実行できるよう設定します。

ここで1点問題。。。
この例では、カスタムコマンドにndk-buildのフルパスを記載しているんですが、チーム開発などには不便ですね。環境設定から値を読み出す方法とかご存知のかたいたらコメントなどいただければありがたいです。

##まとめ
これで、Xamarin.AndroidプロジェクトでNDKネイティブコード含めてビルド・実行する環境が整いました。
プロジェクト内に一元管理することで、ビルド・デバッグのテンポがよくなる、リポジトリを分散させなくてすむなどのメリットが生まれるかと。

17
18
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
18

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?