Xamarin会帮助将win32 DLL移植到android共享库吗?

时间:2013-10-23 10:42:12

标签: android android-ndk xamarin

我正在开发一个项目,我需要在Android应用程序中包含NGSpice模拟库,当然也可以使用它。

我需要将NGSpice windows DLL移植到我的Android应用程序,xamarin在这个任务中会帮助我多远?它是一个win32 dll,它不是基于.Net的dll,请查看NGSpice链接

感谢。

1 个答案:

答案 0 :(得分:1)

是的,可以使用Android NDK

由于一开始阅读所有文档可能有点压倒性,我会给你一个快速浏览。

  1. 安装NDK
  2. 在项目目录
  3. 中创建名为 jni 的文件夹
  4. 在该文件夹中创建一个子文件夹 lib ,并将库中所需的源文件复制到该文件夹​​
  5. jni 文件夹中创建两个文件,wrapper.c和wrapper.h。这些文件应包含本机库周围的高级包装器,适用于使用DllImport从C#端绑定
  6. jni 文件夹中创建名为 Android.mk 的文件
  7. jni 文件夹中创建名为 Application.mk 的文件
  8. 运行 ndk-build
  9. ndk-build成功完成后,在C#项目目录中创建子文件夹 lib ,并将生成的本机库(包括其周围文件夹)复制到 lib 。您的文件夹结构应如下所示:< project> - > 图书馆 - > armeabi x86 (两个文件夹都包含特定于architure的.so文件)。通过建立此文件夹结构,我们确保MonoDroid将自动加载当前运行时体系结构的匹配库。
  10. 在C#项目中创建新的C#类文件 Foo.cs 。此类实现本机库包装器和C#世界之间的绑定粘合。
  11. 利润!
  12. <强> 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需要替换为实际库源文件的名称。

    <强> Application.mk:

    APP_ABI := armeabi armeabi-v7a x86
    

    此行告诉ndk-build您希望支持哪些体系结构。 x86适用于Intel Android HAXM Simulator。

    <强> wrapper.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
    }