dart-lang / native

Dart packages related to FFI and native assets bundling.
BSD 3-Clause "New" or "Revised" License
103 stars 35 forks source link

Using dart:ffi with a xcframework containing static binaries (iOS) #934

Open jtdLab opened 7 months ago

jtdLab commented 7 months ago

Given the libcool.xcframework containing large static binaries like so:

Info.plis
├── ios-arm64_armv7_armv7s
│   ├── libcool.a
├── ios-arm64_x86_64-simulator
│   ├── libcool.a

and a bindings.dart containing the bindings generated with ffigen.

What is the recommended way to use this in my iOS FFI Plugin.

My plugins podspec looks like this:

# To learn more about a Podspec, see http://guides.cocoapods.org/syntax/podspec.html
Pod::Spec.new do |s|
    s.name             = 'my_plugin'
    s.version          = '0.0.1'
    s.summary          = 'My Plugin.'
    s.description      = <<-DESC
    An iOS implementation of My Plugin.
                         DESC
    s.homepage         = 'http://example.com'
    s.license          = { :type => 'BSD', :file => '../LICENSE' }
    s.author           = { 'Your Company' => 'email@example.com' }
    s.source           = { :path => '.' }
    s.dependency 'Flutter'
    s.platform = :ios, '11.0'

    # Flutter.framework does not contain an i386 slice.
    s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
    s.swift_version = '5.0'

    s.source                  = { :http => "path/to/binaries" }
    s.ios.vendored_frameworks = "**/libcool.xcframework"
  end

When opening the dynamic library of the plugin in dart with DynamicLibrary.open('my_plugin.framework/my_plugin') and calling one of the bindings i run into Invalid argument(s): Failed to lookup symbol '<lib_cool_method_a>': dlsym(0x7f97b7a3ecb0, lib_cool_method_a): symbol not found

dcharkes commented 7 months ago

Static libraries are not currently supported.

dart:ffi only provides capabilities to do lookups in dynamic libraries or the current executable.

For static libraries to work, either the Dart code itself would need to be compiled to a static library and then the two static libraries would need to be linked together with the native linker (tracked in https://github.com/dart-lang/sdk/issues/49418), or the static library would need to be compiled into a dynamic library specifying the list of symbols that should be visible for lookup. The latter option becomes useful if we could automate that based on which @Natives are used in a Dart program. But until we have either of those, one should compile to dynamic libraries rather than static libraries.

jtdLab commented 7 months ago

@dcharkes Thanks for the response. Is it somehow possible to compile the static libs mentioned above into a dynamic lib given a header file? If static libs are not yet supported with ffi is it possible to use them via method channels?

dcharkes commented 7 months ago

Is it somehow possible to compile the static libs mentioned above into a dynamic lib given a header file?

Yes, if you invoke the linker with the right flags. But why do you have a static library in the first place? Can't you get a dynamic library instead? (Static libraries are usually not stable as a distribution format.) Can you elaborate on your use case?

If static libs are not yet supported with ffi is it possible to use them via method channels?

I don't know the answer to this.

jtdLab commented 7 months ago

@dcharkes Yeah ;( its closed third party software they only provide a static lib currently (I requested a dynamic one but pending)

I want to include the static libs into an ios version of a flutter plugin following this (see iOS section) to bind to the lib but i run into symbol not found error. If i understand you right, first the static lib has to be compiled to a dynamic one using something like this after that i redo the steps from the first article using the new dynamic lib.

jtdLab commented 7 months ago

When trying the steps you mentioned here i run into many Error (Xcode): Undefined symbol:

Steps:

  1. Create flutter plugin

  2. Copy the mentioned libcool.xcframework to ios/Frameworks

  3. Modify .podspec of the flutter plugin so it contains:

s.vendored_frameworks = 'Frameworks/libcool.xcframework'
s.pod_target_xcconfig = { "OTHER_LDFLAGS" => "-all_load -ObjC" }  
tinyjin commented 3 months ago

Hello, anything new? I have same situation in dynamic libraries with xcframework.

dcharkes commented 3 months ago

I have same situation in dynamic libraries with xcframework.

This issue is about static libraries, not dynamic libraries. Please file a new issue.