Dart FFI can't load dynamic library on Android

1.3k Views Asked by At

I have a simple C++ function compiled into a dylib file that I'm trying to run on an Android phone. The function is super simple, it just adds to numbers and returns the result. However, I keep getting this error: Another exception was thrown: Invalid argument(s): Failed to load dynamic library 'libadd.dylib': dlopen failed: library "libadd.dylib" not found .

I'm really not sure what I'm doing wrong. I've done the following steps: My Dart implementation:

import 'dart:ffi' as ffi;
import 'dart:io' show Platform, Directory;

import 'package:path/path.dart' as path;

typedef C_ADD = ffi.Int Function(
    ffi.Int a, ffi.Int b); // FFI signature of C function
typedef ADD = int Function(int a, int b);

void linkAndCallFunction() {
  var libraryPath = path.join(Directory.current.path, "libadd.dylib");
  final dylib = ffi.DynamicLibrary.open(libraryPath);

  final ADD add = dylib.lookup<ffi.NativeFunction<C_ADD>>("add").asFunction();
  final result = add(40, 2);
  print(result);
}

I've added these to the build.gradle files: build.gradle:

buildscript{
    ext{
        ndkVersion = "25.1.8937393"
    }
    ...

and app/build.gradle:

android {
    ndkVersion rootProject.ext.ndkVersion
    externalNativeBuild {
        cmake {
            path "../../lib/CMakeLists.txt"
        }
    }

This is my CMakeLists.txt file:

cmake_minimum_required(VERSION 3.10.2)
project(add LANGUAGES CXX C)
set(CMAKE_INSTALL_RPATH "$ORIGIN/lib")

add_library(add SHARED ./add.cpp)

and my file structure of the project looks like this:

   lib/
      - add.cpp
      - add.o
      - CMakeLists.txt
      - libadd.dylib
      - main.dart

it also may be worth mentioning that in order to compile add.cpp into a dylib I ran the following commands:

g++ -c add.cpp
ar rvs libadd.dylib add.o

and if you're wondering, add.cpp looks like this:

#define EXPORT extern "C" __attribute__((visibility("default")))
__attribute__((used))

EXPORT
int add(int a, int b){
    return a + b;
}

Where is this error coming from? am I compiling to a dylib incorrectly?

1

There are 1 best solutions below

0
On BEST ANSWER

The answer to this problem was relatively simple, it just stemmed from my lack of knowledge on how Android actually compiles to a static library. Hopefully it helps someone else who is trying to understand how to setup external C++ code in a flutter program.

The static library is generated automatically and is set up in CMakeLists.txt.

Firstly, I moved all the C++ files into the android folder. Then, I set up CMakeLists.txt like this:

cmake_minimum_required(VERSION 3.10.2)

add_library( add  // library name, will create libadd.so

            SHARED

            add.cpp

)

The problem before was that I was trying to manually compile the file myself, when I should have been letting CMakeLists do it instead. According to the android documentation:

"The convention CMake uses to name the file of your library is as follows:

liblibrary-name.so

For example, if you specify "native-lib" as the name of your shared library in the build script, CMake creates a file named libnative-lib.so. " https://developer.android.com/studio/projects/configure-cmake

So when I run the program, the static library is created automatically and placed in the correct place. Then, the Dart FFI can find it with the DynamicLibrary.open() function. In this case, CMakeLists will generate a file called libadd.so, and I can callDynamicLibrary.open('libadd.so') and the program works.