Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Question Using SkiaSharp (Google Graphics/Drawing Library) in Android builds?

Discussion in 'Editor & General Support' started by mikejm_, Dec 5, 2022.

  1. mikejm_

    mikejm_

    Joined:
    Oct 9, 2021
    Posts:
    346
    I have installed SkiaSharp by adding SkiaSharp.dll and libSkiaSharp.dll from this page's prepackaged zip to my Assets/Plugin folder and the following line to csc.rsp:

    http://blog.zarfhome.com/2017/08/using-skiasharp-in-unity.html

    Code (csharp):
    1. -r:Assets\Plugins\SkiaSharp.dll
    This works in Unity Editor on Windows. I can access the SkiaSharp functions/classes. However, when I build to Android and try to run the same functions I get:

    Code (csharp):
    1. 2022/12/04 21:01:00.790 19171 19202 Debug Unity Failed to load native plugin: Unable to lookup library path for 'SkiaSharp'.
    2. 2022/12/04 21:01:00.798 19171 19202 Error Unity DllNotFoundException: libSkiaSharp assembly:<unknown assembly> type:<unknown type> member:(null)
    3. 2022/12/04 21:01:00.798 19171 19202 Error Unity   at (wrapper managed-to-native) SkiaSharp.SkiaApi.sk_memorystream_new()
    4. 2022/12/04 21:01:00.798 19171 19202 Error Unity   at SkiaSharp.SKMemoryStream..ctor () [0x00000] in <d8a986c3a3a54171980f8dabea28fb18>:0
    5. 2022/12/04 21:01:00.798 19171 19202 Error Unity   at SkiaSharp.SKMemoryStream..ctor (System.Byte[] data) [0x00000] in <d8a986c3a3a54171980f8dabea28fb18>:0
    6. 2022/12/04 21:01:00.798 19171 19202 Error Unity   at SkiaSharp.SKBitmap.Decode (System.Byte[] buffer) [0x00011] in <d8a986c3a3a54171980f8dabea28fb18>:0
    I am not familiar with adding third party plugins like this. Is there any trick to making this work or is SkiaSharp likely incompatible with Android?

    Thanks.
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,951
    Usually you have to have slightly different interop calls (eg, not
    __Internal
    but rather the name of the AAB file (which is what I use with Android)).

    I'm not sure how it would connect with a DLL however, and it might be different with Mono vs IL2CPP, but nowadays to publish on google play you need IL2CPP anyway.

    I can however show you sample code from my KurtMaster2D game which builds for Android and all targets, and hopefully that along with the docs might give you an idea? The interop call declarations look like so:

    Code (csharp):
    1. using System.Runtime.InteropServices;
    2.  
    3. public static partial class dispatcher1
    4. {
    5. #if UNITY_IOS || UNITY_WEBGL
    6.     [DllImport ("__Internal")]
    7.     private static extern System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1);
    8.  
    9.     [DllImport ("__Internal")]
    10.     private static extern System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2);
    11.  
    12.     [DllImport ("__Internal")]
    13.     private static extern System.IntPtr dispatcher1_getkpworkbuf();
    14.  
    15.     [DllImport ("__Internal")]
    16.     private static extern void dispatcher1_rendercolor(
    17.     System.IntPtr pixels, int span, int flags);
    18. #elif UNITY_ANDROID
    19.     [DllImport ("vanilib")]
    20.     private static extern System.IntPtr dispatcher1_entrypoint1(int opcode1, int arg1);
    21.  
    22.     [DllImport ("vanilib")]
    23.     private static extern System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2);
    24.  
    25.     [DllImport ("vanilib")]
    26.     private static extern System.IntPtr dispatcher1_getkpworkbuf ();
    27.  
    28.     [DllImport ("vanilib")]
    29.     private static extern void dispatcher1_rendercolor ( System.IntPtr pixels, int span, int flags);
    30. #elif UNITY_STANDALONE_WIN
    31.     [DllImport ("libtest1")]
    32.     private static extern System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1);
    33.  
    34.     [DllImport ("libtest1")]
    35.     private static extern System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2);
    36.  
    37.     [DllImport ("libtest1")]
    38.     private static extern System.IntPtr dispatcher1_getkpworkbuf();
    39.  
    40.     [DllImport ("libtest1")]
    41.     private static extern void dispatcher1_rendercolor( System.IntPtr pixels, int span, int flags);
    42. #elif UNITY_STANDALONE_OSX
    43.     [DllImport ("bundletest1")]
    44.     private static extern System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1);
    45.  
    46.     [DllImport ("bundletest1")]
    47.     private static extern System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2);
    48.  
    49.     [DllImport ("bundletest1")]
    50.     private static extern System.IntPtr dispatcher1_getkpworkbuf();
    51.  
    52.     [DllImport ("bundletest1")]
    53.     private static extern void dispatcher1_rendercolor( System.IntPtr pixels, int span, int flags);
    54. #else
    55.     private static System.IntPtr dispatcher1_entrypoint1( int opcode1, int arg1) { return (System.IntPtr)0; }
    56.     private static System.IntPtr dispatcher1_entrypoint2( int opcode2, string arg2) { return (System.IntPtr)0; }
    57.     private static System.IntPtr dispatcher1_getkpworkbuf() { return (System.IntPtr)0;}
    58.     private static void dispatcher1_rendercolor( System.IntPtr pixels, int span, int flags) { }
    59. #endif
    60. }
     
  3. mikejm_

    mikejm_

    Joined:
    Oct 9, 2021
    Posts:
    346
    Thanks, Kurt. I think the problem is the SkiaSharp files from that website were from 2017 and Android support was likely added after. Therefore I need to build new SkiaSharp dll's. I cloned the github in Visual Studio 2022:

    https://github.com/mono/SkiaSharp.git

    Then I right clicked the SkiaSharp project and through properties set the target build platform to dotnet2.1 which is what I want.

    When I build, I get SkiaSharp.dll but no libSkiaSharp.dll. Trying to use SkiaSharp.dll by itself in Unity gives an error looking for libSkiaSharp.dll. As I understand SkiaSharp.dll is the C# code and libSkiaSharp.dll is the C++ code if that makes sense.

    But I can't figure out how to build the libSkiaSharp.dll. The only reference I see is in the project it says:

    Code (csharp):
    1.  
    2. <ItemGroup Condition="$(TargetFramework.StartsWith('netstandard2.0'))">
    3.     <!-- macOS -->
    4.     <None Include="..\..\output\native\osx\libSkiaSharp*" Link="nuget\runtimes\osx\native\%(Filename)%(Extension)" />
    5.     <!-- Windows -->
    6.     <None Include="..\..\output\native\windows\x64\libSkiaSharp*" Link="nuget\runtimes\win-x64\native\%(Filename)%(Extension)" />
    7.     <None Include="..\..\output\native\windows\x86\libSkiaSharp*" Link="nuget\runtimes\win-x86\native\%(Filename)%(Extension)" />
    8.     <None Include="..\..\output\native\windows\arm64\libSkiaSharp*" Link="nuget\runtimes\win-arm64\native\%(Filename)%(Extension)" />
    9.     <!-- Windows: Nano Server -->
    10.     <None Include="..\..\output\native\nanoserver\x64\libSkiaSharp*" Link="nuget\runtimes\nanoserver-x64\native\%(Filename)%(Extension)" />
    11.     <!-- Linux -->
    12.     <None Include="..\..\output\native\linux\x64\libSkiaSharp*" Link="nuget\runtimes\linux-x64\native\%(Filename)%(Extension)" />
    13.     <None Include="..\..\output\native\linux\x86\libSkiaSharp*" Link="nuget\runtimes\linux-x86\native\%(Filename)%(Extension)" />
    14.     <None Include="..\..\output\native\linux\arm64\libSkiaSharp*" Link="nuget\runtimes\linux-arm64\native\%(Filename)%(Extension)" />
    15.     <None Include="..\..\output\native\linux\arm\libSkiaSharp*" Link="nuget\runtimes\linux-arm\native\%(Filename)%(Extension)" />
    16.     <!-- Linux: Musl -->
    17.     <None Include="..\..\output\native\alpine\x64\libSkiaSharp*" Link="nuget\runtimes\linux-musl-x64\native\%(Filename)%(Extension)" />
    18.     <None Include="..\..\output\native\alpine\x86\libSkiaSharp*" Link="nuget\runtimes\linux-musl-x86\native\%(Filename)%(Extension)" />
    19.     <None Include="..\..\output\native\alpine\arm64\libSkiaSharp*" Link="nuget\runtimes\linux-musl-arm64\native\%(Filename)%(Extension)" />
    20.     <None Include="..\..\output\native\alpine\arm\libSkiaSharp*" Link="nuget\runtimes\linux-musl-arm\native\%(Filename)%(Extension)" />
    21.     <!-- Linux: No Dependencies -->
    22.     <None Include="..\..\output\native\linuxnodeps\x64\libSkiaSharp*" Link="nuget\runtimes\linuxnodeps-x64\native\%(Filename)%(Extension)" />
    23.     <None Include="..\..\output\native\linuxnodeps\x86\libSkiaSharp*" Link="nuget\runtimes\linuxnodeps-x86\native\%(Filename)%(Extension)" />
    24.     <None Include="..\..\output\native\linuxnodeps\arm64\libSkiaSharp*" Link="nuget\runtimes\linuxnodeps-arm64\native\%(Filename)%(Extension)" />
    25.     <None Include="..\..\output\native\linuxnodeps\arm\libSkiaSharp*" Link="nuget\runtimes\linuxnodeps-arm\native\%(Filename)%(Extension)" />
    26.     <!-- Linux: Musl, No Dependencies -->
    27.     <None Include="..\..\output\native\alpinenodeps\x64\libSkiaSharp*" Link="nuget\runtimes\linuxnodeps-musl-x64\native\%(Filename)%(Extension)" />
    28.     <None Include="..\..\output\native\alpinenodeps\x86\libSkiaSharp*" Link="nuget\runtimes\linuxnodeps-musl-x86\native\%(Filename)%(Extension)" />
    29.     <None Include="..\..\output\native\alpinenodeps\arm64\libSkiaSharp*" Link="nuget\runtimes\linuxnodeps-musl-arm64\native\%(Filename)%(Extension)" />
    30.     <None Include="..\..\output\native\alpinenodeps\arm\libSkiaSharp*" Link="nuget\runtimes\linuxnodeps-musl-arm\native\%(Filename)%(Extension)" />
    31.     <!-- WASM -->
    32.     <None Include="..\..\output\native\wasm\**\libSkiaSharp*.a" Link="nuget\build\wasm\%(RecursiveDir)%(Filename)%(Extension)" />
    33.     <None Include="nuget\build\wasm\SkiaSharp.props" Link="nuget\build\wasm\SkiaSharp.props" />
    34.     <None Include="nuget\build\wasm\SkiaSharp.targets" Link="nuget\build\wasm\SkiaSharp.targets" />
    35.   </ItemGroup>
    Any ideas? This is my first time building a dll like this. Is there somewhere I can specify which possible dlls I am building from the project?

    Thanks.
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,951
    You will definitely want to start with their forums.

    If it is C#, it must be compatible with the C# level Unity supports

    If it is C, you might get around building a DLL and instead drop files into Unity in the Plugins/Android folder, which might work, but is generally NOT for the faint of heart.

    As I said for my stuff, I built my C/C++ code into an AAR (Android Archive) for integration with Unity, as the interop code above does. It is
    vanilib-release.aar
    , which is where the DLLImport decorator name comes from.

    BUT... I also could have dropped the C files into Unity directly, which I do nowadays for WebGL on that project.
     
    Last edited: Dec 6, 2022
    mikejm_ likes this.
  5. qaisammari

    qaisammari

    Joined:
    Apr 12, 2021
    Posts:
    10