Back

Xamarin.Forms and C++

Using C++ Android code with Xamarin.Forms

This walkthrough will show the process of creating and using C++ library in Xamarin.Forms project (Only Android).

My Environment

Syntax Description
OS Windows 10 (64bit)
IDE/Compiler VS 2022 Community
Target Android 11

Step 1 - Creating Android Native library in C++

Note

Make sure that Mobile development with C++ component is installed in your Visual Studio.

In Visual Studio, Create A New Dynamic Shared Library (Android) named “MyMathFuncsLib” and for simplicity rename solution to “XamarinFormsCpp”.

Dynamic Shared Library (Android) Project

Delete the auto-created files, then create 4 new files named MyMathFuncs.h, MyMathFuncs.cpp, MyMathFuncsWrapper.h, and MyMathFuncsWrapper.cpp and copy the below codes in them (Respectively).

MyMathFuncs.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
namespace MathFuncs
{
    class MyMathFuncs
    {
    public:
        double Add(double a, double b);
        double Subtract(double a, double b);
        double Multiply(double a, double b);
        double Divide(double a, double b);
    };
}

MyMathFuncs.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include "MyMathFuncs.h"

namespace MathFuncs
{
    double MyMathFuncs::Add(double a, double b)
    {
        return a + b;
    }

    double MyMathFuncs::Subtract(double a, double b)
    {
        return a - b;
    }

    double MyMathFuncs::Multiply(double a, double b)
    {
        return a * b;
    }

    double MyMathFuncs::Divide(double a, double b)
    {
        return a / b;
    }
}

MyMathFuncsWrapper.h

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#include "MyMathFuncs.h"
using namespace MathFuncs;

extern "C" {
    MyMathFuncs* CreateMyMathFuncsClass();
    void DisposeMyMathFuncsClass(MyMathFuncs* ptr);
    double MyMathFuncsAdd(MyMathFuncs* ptr, double a, double b);
    double MyMathFuncsSubtract(MyMathFuncs* ptr, double a, double b);
    double MyMathFuncsMultiply(MyMathFuncs* ptr, double a, double b);
    double MyMathFuncsDivide(MyMathFuncs* ptr, double a, double b);
}

MyMathFuncsWrapper.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include "MyMathFuncsWrapper.h"

MyMathFuncs* CreateMyMathFuncsClass()
{
    return new MyMathFuncs();
}

void DisposeMyMathFuncsClass(MyMathFuncs* ptr)
{
    if (ptr != nullptr)
    {
        delete ptr;
        ptr = nullptr;
    }
}

double MyMathFuncsAdd(MyMathFuncs* ptr, double a, double b)
{
    return ptr->Add(a, b);
}

double MyMathFuncsSubtract(MyMathFuncs* ptr, double a, double b)
{
    return ptr->Subtract(a, b);
}

double MyMathFuncsMultiply(MyMathFuncs* ptr, double a, double b)
{
    return ptr->Multiply(a, b);
}

double MyMathFuncsDivide(MyMathFuncs* ptr, double a, double b)
{
    return ptr->Divide(a, b);
}

By now your project structure should look like this:

Dynamic Shared Library (Android) Project - Configuration

Info

For information about above codes, refer to This link

Now we should configure the project. First make sure that project is in Release for ARM64 configuration, then in Project Properties -> Configuration -> General change the target API level to the maximum value that is posible for your needs.

Dynamic Shared Library (Android) Project - Configuration

And also rename the Root Namespace of the project to MathFuncs.

Dynamic Shared Library (Android) Project - Properties

At the end build the project (again make sure that project is in Release for ARM64 configuration!). If every thing is OK, the project should build successfully and a file named libMathFuncs.so is created in project output directory (SolutionDir\MyMathFuncsLib\ARM64\Release).

Step 2 - Creating Xamarin.Form application

Right click on the solution on Solution Explorer, then select New Project from Add menu. Choose Mobile App (Xamarin.Forms), and name it XamarinApp and create the project. In the next window select Blank as app template and only select Android as platform.

Xamarin.Forms Project

In Solution Explorer, right click on XamarinApp.Android and select Set As Startup Project.

Tip

To make sure that every thing in the XamarinApp.Android project is ok, before going any further, first build and deploy the project.

Step 3 - Adding the C++ library to the Xamarin Forms Project

Add a new folder to the XamarinApp.Android project named lib and another new folder to the lib folder named arm64-v8a and copy the libMathFuncs.so from the privious step to this folder. Then select the libMathFuncs.so and in Properties window, set the build action to AndroidNativeLibrary.

Info

If you are using the .so file in a Xamarin.Android library project insted of Xamarin.Android application project, replace AndroidNativeLibrary with EmbeddedNativeLibrary. For more information refer to This link

Adding .so file to the project

Step 4 - Creating Wrapper of C++ library for C#

Add a new folder to the XamarinApp.Android project named Models and then add a new class named MyMathFuncs.cs in Models folder and replace the content of MyMathFuncs.cs with bellow code:

MyMathFuncs.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using Microsoft.Win32.SafeHandles;
using System;
using System.Runtime.InteropServices;

namespace XamarinApp.Droid.Models
{
    internal class MyMathFuncsSafeHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        public MyMathFuncsSafeHandle() : base(true) { }

        public IntPtr Ptr => this.handle;

        protected override bool ReleaseHandle()
        {
            MyMathFuncsWrapper.DisposeMyMathFuncs(handle);
            return true;
        }
    }

    internal static class MyMathFuncsWrapper
    {
        const string DllName = "libMathFuncs.so";

        [DllImport(DllName, EntryPoint = "CreateMyMathFuncsClass")]
        internal static extern MyMathFuncsSafeHandle CreateMyMathFuncs();

        [DllImport(DllName, EntryPoint = "DisposeMyMathFuncsClass")]
        internal static extern void DisposeMyMathFuncs(IntPtr ptr);

        [DllImport(DllName, EntryPoint = "MyMathFuncsAdd")]
        internal static extern double Add(MyMathFuncsSafeHandle ptr, double a, double b);

        [DllImport(DllName, EntryPoint = "MyMathFuncsSubtract")]
        internal static extern double Subtract(MyMathFuncsSafeHandle ptr, double a, double b);

        [DllImport(DllName, EntryPoint = "MyMathFuncsMultiply")]
        internal static extern double Multiply(MyMathFuncsSafeHandle ptr, double a, double b);

        [DllImport(DllName, EntryPoint = "MyMathFuncsDivide")]
        internal static extern double Divide(MyMathFuncsSafeHandle ptr, double a, double b);
    }

    public class MyMathFuncs : IDisposable
    {
        readonly MyMathFuncsSafeHandle handle;

        public MyMathFuncs()
        {
            handle = MyMathFuncsWrapper.CreateMyMathFuncs();
        }

        protected virtual void Dispose(bool disposing)
        {
            if (handle != null && !handle.IsInvalid)
                handle.Dispose();
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        public double Add(double a, double b)
        {
            return MyMathFuncsWrapper.Add(handle, a, b);
        }

        public double Subtract(double a, double b)
        {
            return MyMathFuncsWrapper.Subtract(handle, a, b);
        }

        public double Multiply(double a, double b)
        {
            return MyMathFuncsWrapper.Multiply(handle, a, b);
        }

        public double Divide(double a, double b)
        {
            return MyMathFuncsWrapper.Divide(handle, a, b);
        }
    }

}

Info

For information about above codes, refer to This link

Step 5 - Using the Wrapper in Xamarin.Forms

Add a new folder named Interfaces to the XamarinApp project. then add a new interface named IMathFuncs.cs to this folder.

Interface for Xamarin App

Replace the content of IMathFuncs.cs with this code:

IMathFuncs.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
namespace XamarinApp.Interfaces
{
    public interface IMathFuncs
    {
        double Add(double a, double b);
        double Subtract(double a, double b);
        double Multiply(double a, double b);
        double Divide(double a, double b);
    }
}

Add a new folder named DependencyService to the XamarinApp.Android project, then add a class to it named MathFuncs.cs and replace its content with:

MyMathFuncs.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
using XamarinApp.Droid.DependencyService;
using XamarinApp.Droid.Models;
using XamarinApp.Interfaces;
using Xamarin.Forms;

[assembly: Dependency(typeof(MathFuncs))]
namespace XamarinApp.Droid.DependencyService
{
    public class MathFuncs : IMathFuncs
    {
        public double Add(double a, double b)
        {
            MyMathFuncs o = new MyMathFuncs();
            return o.Add(a, b);
        }
        public double Subtract(double a, double b)
        {
            MyMathFuncs o = new MyMathFuncs();
            return o.Subtract(a, b);
        }
        public double Multiply(double a, double b)
        {
            MyMathFuncs o = new MyMathFuncs();
            return o.Multiply(a, b);
        }
        public double Divide(double a, double b)
        {
            MyMathFuncs o = new MyMathFuncs();
            return o.Divide(a, b);
        }
    }
}

Finally to call a function in Xamarin.Forms application, i.e. XamarinApp in this example:

1
2
// Calling 'Add' function implemented in C++ library:
double c = DependencyService.Get<IMathFuncs>().Add(10, 12);

Source Code

Source code of this walkthrough.


Refrences:

  1. Walkthrough: Using C/C++ with Xamarin
  2. Use C/C++ libraries with Xamarin
  3. Xamarin.Android Using Native Libraries
Built with Hugo
Theme Stack designed by Jimmy