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。这些文件应包含适用于使用 DllImport 从 C# 端绑定的本机库的高级包装器
  5. jni文件夹中创建一个名为Android.mk的文件
  6. jni文件夹中创建一个名为Application.mk的文件
  7. 运行ndk-build
  8. 一旦 ndk-build 成功完成,在您的 C# 项目目录中创建子文件夹lib并将生成的本机库(包括其周围的文件夹)复制到lib。您的文件夹结构应如下所示:<project> -> libs -> armeabix86(两个文件夹都包含特定于架构的 .so 文件)。通过建立这个文件夹结构,我们确保 MonoDroid 会自动加载当前运行时架构的匹配库。
  9. 在 C# 项目中创建新的 C# 类文件Foo.cs。此类实现了本机库包装器和 C# 世界之间的绑定胶水。
  10. 利润!

安卓.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 适用于英特尔 Android HAXM 模拟器。

包装器.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 */

包装器.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 回答