Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin.Android: How do you link a static library?

I am trying to link a static library (foo.a) - which contains C++ code - in an Xamarin.Android project following the directions found in Xamarin's docs. Neither the "path sniffing method," nor the "Abi element within the project file" method seems to work.

Using either method I get unhandled exceptions when I attempt to call into the library functions:

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

I should mention that I have had no trouble linking and calling into this library (built for armv7, armv7s) with my Xamarin.iOS project using the "additional mtouch arguments" -cxx method described here. All of my DLLImports are the same across platforms...

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

So, what am I missing?

FYI: I am using Xamarin Studio 4.0.5 (build 4), Xamarin.Android 4.6.4 (Business Edition)

like image 589
danb Avatar asked May 14 '13 00:05

danb


People also ask

How are static libraries linked?

Static libraries are created by copying all necessary library modules used in a program into the final executable image. The linker links static libraries as a last step in the compilation process. An executable is created by resolving external references, combining the library routines with program code.

Can a static library have dependencies?

So what is a Static library?? When linked like this the library is called a static library, because the library will remain unchanged unless the program is recompiled. This is the most straight forward way of using a library as the final result is a simple executable with no dependencies.

What is linker in xamarin forms?

Xamarin. Android applications use a linker to reduce the size of the application. The linker employs static analysis of your application to determine which assemblies are actually used, which types are actually used, and which members are actually used.

How do static libraries work?

In computer science, a static library or statically-linked library is a set of routines, external functions and variables which are resolved in a caller at compile-time and copied into a target application by a compiler, linker, or binder, producing an object file and a stand-alone executable.


1 Answers

I realize this question is over a year old, but since I recently had to do exactly this, and hit my head in the same spot, I'll have a go at it anyway...

TL;DR: you cannot link static libraries with Xamarin for Android, you can only link dynamic libraries (.so)

Steps:

  • If your library is written in C you can skip the first step. But if your lib is written in C++ you must first declare your publicly exported functions as C-functions in your code (i.e. you have to put them inside an #extern "C" { } block). If you don't do this your function names will get subjected to C++ name mangling and Xamarin will not be able to find them.
extern "C"
{
  void my_function(bool someParameter);
}
  • Using the Android NDK, compile your library to a dynamic link library (.so). A static library (.a) will not do. This is where I hit my head, as this is not that clear from the documentation. Adding to the confusion, on IOS it's the exact opposite: you can link static .a libs only there (as per the AppStore policies).
  • Do this for each processor architecture you wish to support (typically, armeabi, armeabi-v7a and x86)
  • From here on I assume you have a set of .so libraries, one for each processor architecure. The libraries are all named libX.so, where X is the project name of your library. E.g. "libmylibrary.so".
  • In your Xamarin Android project, add a folder "libs" below the project root. (You can use another name as well if you wish)
  • Below the folder "libs", create three child folders, named "armeabi", "armeabi-v7a" and "x86" respectively. Copy one of your .so files to each of these child folders (the one corresponding to the same processor architecture). This enables the Xamarin "path sniffing" feature that will select the right library for the right processor architecture.
  • Include the the three .so files in your project and for each one set the "Build Action" property to "AndroidNativeLibrary"
  • Now add the entry functions as static methods to a Xamarin class with the proper DllImport attributes:
namespace MyApp
{
    public static class MyLibrary
    {
       [DllImport("libmylibrary", EntryPoint = "my_function")]
       public static extern void MyFunction(Boolean someParameter);
    }
}
  • That's it. You should now be able to call MyLibrary.MyFunction() from your Xamarin C# code
like image 143
wolkenjager Avatar answered Oct 11 '22 09:10

wolkenjager