Loading native C library from Objective-C in Flutter plugin - ios

I have a native C library (.so) build in versions for android and iOS. I want them to be used in a flutter app I am building.
For android I use System.loadLibrary() in Java to load the file (wrapped in JNI) and it is included via the Gradle build system/CMake.
But how do I get the same for iOS in objective C ?

Seems like I can use dlopen() on the library and then dlsym() every single function to get their symbol into the app at runtime. Seems pretty dump but I guess it could work (when I at some point have convinced the buildsystem to include the lib into the actual package it builds.

Related

How can I add iOS support via dart ffi without adding flutter sdk as a dependency?

I am working on the dart_ping package and although it currently is tagged with iOS support, it does not actually support iOS. This is due to the way pub.dev detects supported platforms. I have filed an issue on dart-sdk repo.
Nonetheless, I would like to add iOS support while still preserving support for dart native. Right now, dart_ping works by calling the host OS's ping binary. The ping binary is available on Windows, macOS, Linux, and Android but not on iOS.
Current methods of performing a ping on iOS use native Objective-C code and call them via either method channels or ffi. Since method channels are a flutter feature rather than a dart feature, using them would require dart_ping to depend on the flutter sdk, which would prevent it from being used in a dart native application (perhaps server side).
Ffi on the other hand, is a dart native feature and is capable of doing what I want. However, I cannot seem to find a way to include the iOS framework/library/binary for ping in my dart_ping package in a way that instructs a flutter application to include it and link it to the iOS target/runner.
Is there any way to keep dart native support in my package while also supporting the edge case of iOS needing an extra non-dart framework? Even federated plugins depend on the flutter sdk. It seems to me that we need a pure dart equivalent to the federated plugin system.
TLDR: How do I add a pre-compiled iOS framework or binary to a dart package without depending on the flutter sdk and call it only when the package is used on iOS ?
For your specific case of adding iOS support only for Flutter users of your package but keeping the package as pure Dart without a dependency on the Flutter SDK should be possible by having a Flutter plugin package that depends on your Dart package.
In the pure Dart package you can have FFI calls to a native iOS library, but its actually the Flutter plugin package that supplies the native iOS library per the Flutter documentation for using FFI.
You would of course need to make it very clear in the documentation for your pure Dart package that for iOS, it should only be used via the "wrapper" plugin package.
Unfortunately this is a rather convoluted way to do it, but I don't know of a better way to achieve this as of now.
There is further discussion on this topic in the comments in this issue, which as of today is still open.

How to avoid "libraries attached to project that were compiled with kotlin/native compiler" error?

I am working on a Kotlin Multiplatform Mobile project. Tried adding in libraries for KMM, but I am getting
There are __ third-party libraries attached to the project that were compiled with an older Kotlin/Native compiler and can't be read in IDE.
The android project builds without problem so I was wondering if whether this error is only a warning and doesn't not affect the application at all?
Is there anyway to avoid this issue? How can I know if a library could be used for Kotlin Native?
Kotlin/Native doesn't guarantee binary compatability between versions - although as of 1.4 minor versions are experimentally binary backwards compatible. e.g. 1.4.10 should be compatible with 1.4.20 in the same project.
The easiest way to avoid the error is to ensure you're using KMM libraries with the same kotlin version as the kotlin version your project uses. Same goes for the IDE plugin.
Generally kotlin libraries by Jetbrains stay very up to date, as well as bigger libraries like SqlDelight. But smaller third party libraries can fall behind.
This issue is being actively worked on.

Can Point Cloud Library be used with iOS apps?

I would like to port the arithmetic processing (written in C ++) using Point Cloud Library to an iOS application (swift). Is it possible to use PCL with swift?
There is no supported version of PCL compiled for arm64 yet. However, the following project may be useful:
https://github.com/patmarion/pcl-superbuild
It has difficulties with the current version of Boost for iOS, so you can replace Boost with a project like this:
https://github.com/danoli3/ofxiOSBoost/
Or maybe you can use the precompiled libraries from a project like this:
https://github.com/stevenroach7/3DScanr/tree/master/PCL_Build_Artifacts

How to obfuscate Objective C code of Cordova hybrid app?

I have an Ionic v1 / Cordova mobile app and I need to obfuscate all sources. For obfuscation of Javascript I have used https://github.com/javascript-obfuscator/javascript-obfuscator and for Java for Android I have used https://github.com/greybax/cordova-plugin-proguard. As I couldn't find any cordova plugin for obfuscation of Objective C and I decided to use https://github.com/preemptive/PPiOS-Rename.
However, after obfuscation with PPiOS-Rename, there seems to be a problem with obfuscation of cordova plugins and I'm unable to run the app correctly. If I remove the plugins from obfuscation process the app would work but I need to make obfuscated also the code of plugins.
Does anybody have experience with obfuscating the Objective C code of Cordova app please?
Thanks!
The problem that you have is that Cordova relies on a bridge between your app code written in Javascript and the underlying native code in order to function.
By obfuscating all of the Objective C code, the Javascript layer is unaware of this, and can no longer find the native class names it is looking for.
For example, let's suppose you have included cordova-plugin-device in your app.
Its <feature> definition for iOS maps the Device feature name to the CDVDevice class.
Let's suppose your Cordova app calls the plugin method device.getInfo().
This in turn invokes a call to cordova.exec() which calls the Device feature with the getDeviceInfo action.
Under the hood, Cordova looks up Device to find the native class name it's mapped to (CDVDevice) and then on the iOS platform it attempts to call the getDeviceInfo() member function on this class.
However, by running the PPiOS-Rename tool, you have obfuscated both the class name (CDVDevice) and the function name (getDeviceInfo()) so Cordova cannot find the class or function to invoke, so will throw an error.
In this case you'd need to exclude the CDVDevice using the filter option provided by PPiOS-Rename, for example:
ppios-rename --analyze -F 'CDVDevice' /path/to/program.app/program
If you wish to proceed with obfuscating the Objective C layer of your Cordova app, you will have to add exclusions for all of the class and function names which Cordova calls explicitly from the Javascript layer.
This includes any Cordova plugin interface classes in your project, and possibly classes belonging to the Cordova framework itself (as cordova-plugin-proguard does for ProGuard on Android.

Can I get the Unity3D engine version in Xcode and how to do a conditional compile based on the version?

I'm working on a plugin in Unity3D for iOS. For some reason, I need to specify some code in the native code (.mm in Xcode) to be compiled under before Unity3D 4.1 and other be compiled after Unity3D 4.1(including). Maybe something like this:
#if UNITY_VERSION < UNITY_4_1
//Some code be compiled before Unity4.1
#else
//Some code for new version
#endif
I know there is a Platform Dependent Compilation in the Unity3D Editor, but how can I get the engine's version in Xcode and do a "Unity Engine version based condition compilation"? Any suggestion will be appreciated!
Edit: Maybe I can write two .mm files for different version and delete one of them in [PostProcessAttribute]. But I don't think it is a good idea...
It isn't exactly clear on what you are trying to do. Are you building your native code by injecting into the XCode project that Unity creates? Or are you building your native code to a library that is included by Unity during the build?
AFAIK there is no way for XCode to know ahead of time which version of Unity you are using without examing the install of Unity and figuring out a way to determine that.
If you doing the latter, i.e. building a native code library that is included into Unity's build. You would need two separate libraries in that case, and instruct the user to include whichever one is relevant.
If you are doing the former, i.e. injecting new native code into the XCode project that Unity created then Unity does export the #defines so you could then determine which version of Unity your native code needs to compile against.

Resources