1

私は、Android アプリケーションに NGSpice シミュレーション ライブラリを含め、もちろんそれを使用できるようにする必要があるプロジェクトに取り組んでいます。

NGSpice Windows DLL を Android アプリケーションに移植する必要がありますが、xamarinはこのタスクでどの程度役立ちますか? これは win32 dll であり、.Net ベースの dll ではありません。NGSpiceリンクをご覧ください。

ありがとう。

4

1 に答える 1

1

はい、Android NDKを使用して可能です。

すべてのドキュメントを読むのは、最初はやや圧倒される可能性があるため、簡単に説明します。

  1. NDK をインストールする
  2. プロジェクト ディレクトリ内にjniという名前のフォルダーを作成します。
  3. そのフォルダー内にサブフォルダーlibを作成し、必要なライブラリのソース ファイルをそのフォルダーにコピーします。
  4. jniフォルダー内に、wrapper.c と wrapper.h の 2 つのファイルを作成します。これらのファイルには、DllImport を使用して C# 側からバインドするのに適した、ネイティブ ライブラリの高レベルのラッパーが含まれている必要があります。
  5. jniフォルダー内にAndroid.mkという名前のファイルを作成します。
  6. jniフォルダー内に、Application.mkという名前のファイルを作成します。
  7. ndk-build を実行します
  8. ndk-build が正常に完了したら、C# プロジェクト ディレクトリ内にサブフォルダーlibを作成し、周囲のフォルダーを含む生成されたネイティブ ライブラリをlibにコピーします。フォルダ構造は次のようになります: <project> -> libs -> armeabi and x86 (両方のフォルダにアーキテクチャ固有の .so ファイルが含まれています)。このフォルダー構造を確立することで、MonoDroid が現在のランタイム アーキテクチャに一致するライブラリを自動的に読み込むようになります。
  9. C# プロジェクト内に新しい C# クラス ファイルFoo.csを作成します。このクラスは、ネイティブ ライブラリ ラッパーと C# の世界との間の結合のりを実装します。
  10. 利益!

Android.mk:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := libFoo
LOCAL_SRC_FILES := wrapper.c lib/source1.c lib/sourcen.c

include $(BUILD_SHARED_LIBRARY)

注: lib/source1.c と lib/sourcen.c は、実際のライブラリ ソース ファイルの名前に置き換える必要があります。

アプリケーション.mk:

APP_ABI := armeabi armeabi-v7a x86

この行は、サポートしたいアーキテクチャを ndk-build に伝えます。x86 は Intel Android HAXM Simulator 用です。

ラッパー.h:

#pragma once

typedef struct _InternalState
{
    FILE *m_pFile;
} InternalState;

//////////////////////
// Public API

#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */

InternalState *FooCreate(int foo);
void FooDoStuff(InternalState *pState);

#ifdef __cplusplus
}
#endif /* __cplusplus */

wrapper.c:

//////////////////////
// Public API

InternalState *FooCreate(int foo)
{
  // Initialize actual library here
  // return state if necessary
}

void FooDoStuff(InternalState *pState)
{
  // Call actual library here
}

Foo.cs:

public class Foo :
  IDisposable
{
  private IntPtr handle;
  private bool disposed;

  private Foo(IntPtr handle)
  {
    this.handle = handle;
  }

  ~Foo()
  {
    Dispose(false);
  }

  public void Dispose()
  {
    Dispose(true);
    GC.SuppressFinalize(this);
  }

  public void Dispose(bool disposing)
  {
    disposed = true;

    Close();
  }

  #region Native Imports

  [DllImport("libFoo")]
  private static extern IntPtr FooCreate(int seed);
  [DllImport("libFoo")]
  private static extern void FooDoStuff(IntPtr pHandle);

  #endregion

  private void VerifyHandle()
  {
    if (handle == IntPtr.Zero)
      throw new InvalidOperationException("Handle not initialized");
  }

  #region Public API

  public static Foo FromSeed(int seed)
  {
    IntPtr handle = FooCreate(seed);
    if(handle == IntPtr.Zero)
      throw new System.Exception("Failed to create native object");

    return new Foo(handle);
  }

  public void DoStuff()
  {
    VerifyHandle();

    FooDoStuff(handle);
  }

  #endregion
}
于 2013-10-23T10:58:57.383 に答える