Xamarin.Android:你如何链接静态库?

时间:2013-05-14 00:36:08

标签: xamarin.android xamarin

我正在尝试在Xamarin的文档中找到directions之后的Xamarin.Android项目中链接一个包含C ++代码的静态库(foo.a)。 “路径嗅探方法”和“项目文件中的Abi元素”方法似乎都不起作用。

当我尝试调用库函数时,使用任一方法都会得到未处理的异常:

I/mono( 2591): [ERROR] FATAL UNHANDLED EXCEPTION: System.EntryPointNotFoundException: ...

我应该提一下,我使用“附加的mtouch参数”-cxx方法here与我的Xamarin.iOS项目链接和调用这个库(为armv7,armv7s构建)没有问题。我的所有DLLImports都是跨平台的......

[DllImport(Import.lib, CallingConvention=CallingConvention.Cdecl )]
internal static extern IntPtr FooMethodName(args);

那么,我错过了什么?

供参考: 我正在使用Xamarin Studio 4.0.5(build 4),Xamarin.Android 4.6.4(商业版)

1 个答案:

答案 0 :(得分:9)

我意识到这个问题已经超过一年了,但是由于我最近不得不做到这一点,而且在同一个地方碰到了我的脑袋,无论如何我都会去看看......

TL; DR:您无法将静态库与Xamarin for Android链接,您只能链接动态库(.so)

步骤:

  • 如果您的库是用C语言编写的,则可以跳过第一步。但是,如果您的lib是用C ++编写的,则必须首先在代码中将公开导出的函数声明为C函数(即必须将它们放在#extern“C”{}块中)。如果你不这样做,你的函数名将受到C ++名称修改,Xamarin将无法找到它们。
extern "C"
{
  void my_function(bool someParameter);
}
  • 使用Android NDK,将库编译为动态链接库(.so)。静态库(.a)将。这就是我的目标,因为文档中并不清楚这一点。更令人困惑的是,在IOS上它是完全相反的:你可以在那里链接静态.a libs (根据AppStore政策)。
  • 为您希望支持的每个处理器架构执行此操作(通常为armeabi,armeabi-v7a和x86)
  • 从这里开始,我假设您有一组.so库,每个处理器架构一个。这些库都名为libX.so,其中X是库的项目名称。例如。 “libmylibrary.so”。
  • 在您的Xamarin Android项目中,在项目根目录下添加一个“libs”文件夹。 (如果您愿意,也可以使用其他名称)
  • 在文件夹“libs”下面,分别创建三个名为“armeabi”,“armeabi-v7a”和“x86”的子文件夹。将一个.so文件复制到每个子文件夹(对应于相同处理器体系结构的子文件夹)。这使得Xamarin“路径嗅探”功能能够为正确的处理器架构选择合适的库。
  • 在项目中包含三个.so文件,并为每个文件设置“Build Action”属性为“AndroidNativeLibrary”
  • 现在将条目函数作为静态方法添加到具有正确DllImport属性的Xamarin类中:
namespace MyApp
{
    public static class MyLibrary
    {
       [DllImport("libmylibrary", EntryPoint = "my_function")]
       public static extern void MyFunction(Boolean someParameter);
    }
}
  • 就是这样。您现在应该可以从Xamarin C#代码中调用MyLibrary.MyFunction()