Categories
Programming

Calling C/C++ libraries from Xamarin code

The Xamarin platform allows developing iOS and Android applications entirely in C#. Sometimes, however, some legacy code may be too large or complex to make porting it to C# for your mobile app worthwhile. Most examples found online show you how to use existing Objective-C libraries in Xamarin.iOS and existing Java libraries in Xamarin.Android. However, it is entirely possible to call C code from a Xamarin app. Microsoft’s recent support for C/C++ on iOS and Android in Visual Studio can make this a simple task.

You will need the sources for the code you want to call to compile it for iOS and Android. The code cannot access any libraries which you only have binaries for that have been compiled for other platforms.

To get started, create a new C++ cross-platform project using Visual Studio 2015.
Create new cross-platform project
You will need to have the corresponding Visual Studio package installed to have this option available.
Visual Studio Setup Cross-Platform Mobile C++
This will create three projects: one for Android, one for iOS, and a shared project.
Project structure

It is important to understand the shared project concept for this. The code in the shared project does not result in a DLL or library being generated. A shared project can hold any type of file. Projects referencing the shared project can access code from any file in the shared project. The code will then be compiled in the context of the referencing project. If code is not referenced, it is not compiled. For this reason, it is necessary to have calls into all code needed contained in the platform-specific projects. This means that the platform-specific C/C++ projects need to contain code, too. This code can be identical in the Android and iOS projects and reside in the same files. Unlike in .NET projects, file linking is not needed for C++ projects; source code files do not have to reside inside a project’s folder or subfolder.

In the example, I’ve created a simple function clib_add_internal() that add two integers and resides in the shared project.


This code is called from a function in the platform-specific projects.

For the example code, this doesn’t make any sense. For a real project, you will put any call that needs to be directly invoked from the .NET code (your interface) into the platform-specific projects while underlying code can reside in the shared project.

The calls from .NET will be using P/Invoke since C++/CLI is not available on iOS or Android. So the basic P/Invoke rules apply for your interface’s code: Either the code is plain C or, if you are using C++, the calls are either plain functions or static methods and contain only POC parameters and return values.

For the iOS project, the output format needs to be changed to a static library (.a file) since iOS does not allow dynamically loading code. For Android, a dynamic library (.so) should be built.

iOS Settings
Android Settings

While the Android library can be compiled within Visual Studio, compiling the iOS library needs a connection to a build agent on the Mac. This is not the regular Xamarin.iOS installation on a Mac but a Microsoft tool that is installed on OS X using npm. Visual Studio will communicate with this tool through TCP/IP.

Connection to build host

To call the native code, create a Xamarin project for iOS and Android each. Include the native libraries in the respective Xamarin projects.

On iOS, if you’re targeting multiple processor architectures (either supporting pre-iPhone 5s or supporting the simulator), you can build the iOS project for multiple platforms using the dropdown in the toolbar. Then, combine the libraries into one using lipo according the Xamarin docs. On Android, you’ll need to modify the .csproj according to the Xamarin documentation to specify the .so files for each platform.

The calls into the native code are regular P/Invoke calls (although DLLs don’t play a role here). On Android, you specify the name of the shared library.

On iOS, use the special Mono name __Internal to call into the static library.

And that’s it! You can find the example code at https://github.com/lothrop/XamarinNative. In the example, I put the C# marshaling code into another shared project that is referenced by the Xamarin.iOS and Xamarin.Android projects.

11 replies on “Calling C/C++ libraries from Xamarin code”

Thank you for your good article!

but, I don’t understand this sentence.

「So the basic P/Invoke rules apply for your interface’s code: Either the code is plain C or, if you are using C++, the calls are either plain functions or static methods and contain only POC parameters and return values.」

Could you show me some code for me ?

The C++ you’re calling will either have to be outside a class

int doSomething(int someVariable);

or will have to be a static method

class A
{
static int doSomething(int someVariable);
};

Parameters and return value can’t be other classes, so int, bool, const char* are fine, std::string is not.

When I build and run I get EntryPointNotFound at Clib.Add in the following method:

partial void UIButton21_TouchUpInside(UIButton sender)
{
var left = int.Parse(Left.Text);
var right = int.Parse(Right.Text);
var result = CLib.Add(left, right).ToString(CultureInfo.InvariantCulture);
Result.Text = result;
}

Thanks for the great article!

I can get everything worked by following the instructions.

Now I want to add “ARMV7S” CPU support in the list. I tried but could not get it done on “Configuration Manager”. Could you please help me how to do that?

Thank you very much!

The code base builds fine but while deploying on the 5″ kitkat Visual studio emulator for Android, I get a error dialog that says, “Unfortunately, Droid has stopped” and quits.

Any ideas, what I am missing?

Also, if I have to debug into the C/C++ code, can you provide the steps?

-Thanks

I had the entry point not found error in my iOS project as well. To fix it, I added libClib.iOS.a to the project’s Native References (Right click on Native References in the iOS project, then Add, Existing Item and choose the libClib.iOS.a file from the iOS directory).

I just tried running this with VS 2017 and can’t get it to compile. I’m new to the Xamarin cross-platform development but did get it to run the standard Hello.IOS (Phoneword) examples using VS 2017under Widows 7 machine and my MacBook Air.

Some details: SDK Version is 11.2 and Xcode on the mac is 9.2 (although VS seems to restrict me to Xcode 6.2 Toolset platform). Is set the Plattform to iPhoneSimulator and the device to iPhone 6 IOS 11.2.

Without getting too bogged down with details, the initial error I get is about i386 32-bit architecture not supported. So I changed the solution configuration to ARM64 (also tried x64). Had to change the IOS Build Supported Architecture to x86_64. After doing so I get “Native linking failed, undefined symbol: _clib_add”. Any help would be appreciated.

Hey I able to run the provided code in github as it is but when I try to make changes in C code and regenerate .so file, the .so files gets generated and I add it to Droid project but then after it stops working, it throws error :- System.DllNotFoundException: libCLib

-Thanks

I am trying to modify your code by adding my function in your code.Every time I am running the code error is coming as *.dll not found.I have set all the properties as I found in your code but still I am getting the same exception.Kindly revert back.

Leave a Reply

Your email address will not be published. Required fields are marked *