dart-lang / native

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

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

Open jtdLab opened 1 year ago

jtdLab commented 1 year 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 12 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 12 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 12 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 12 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 11 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 8 months ago

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

dcharkes commented 8 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.

Alexufo commented 1 month ago

@jtdLab I got duplicate symbols

  duplicate symbol '_OBJC_IVAR_$_OBJCImageRef.ptr' in:
      /Users/user/Desktop/o/example/ios/Build/Products/Debug-iphonesimulator/o/libo.a[arm64][3](o_image.o)
      /Users/user/Desktop/o/example/ios/Build/Products/Debug-iphonesimulator/XCFrameworkIntermediates/o/ok/libo-ios.a[arm64][1075](o_image.mm.obj)