My team owns an Android (Kotlin) and iOS (Swift) app. The app is responsible for processing data, submitting to ML models, and then displaying results in a UI. We chose to do a lot of that processing in a shared Rust component. What we have found is a high overhead of bridging Kotlin/Swift to Rust. Some core logic has also seeped into our bridging code resulting in some duplication (exactly what we were trying to avoid).
With that, those of you who have found yourselves in similar situations, which language would you choose to be shared between your Android and iOS app (if any)?
I use c++ rather than rust because as much as I would love to use the best language its just not so well supported on mobile compared to c/c++. I'm not sure how well flutter ffi does using rust compared to more mainstream approaches its possible that flutter ffi is more friendly to rust than jni/kotlin.
One way would be to host a script engine and run the script language, e.g. JavaScript. Another would be to create your own grammar and simultaneously translate to Kotlin and Swift. You could even use a strict subset of either Kotlin or Swift then you'd only have to deal with one translator.
In Go, there is an official, experimental project called gomobile [0] that allows one to generate a Java or Objective C binding to be used in mobile projects based on Go source code.
It comes with some restrictions and is still deemed experimental. But it could be a viable choice in the days to come.
Gomobile bridges Java and ObjectiveC/Swift to Go, and probably entails the same overhead the author is trying to avoid.
Shameless plug: If you like Go and immediate mode UIs in particular, Gio[0] runs the same Go code across desktop and mobile alike. No bridging or native code required.
If you like a more mature framework and don't mind Dart, I think Flutter is an attractive toolkit. I started Gio wanting to write a Flutter clone in Go before going for the immediate mode design.
Came here to mention nim that I've followed with great interest. As it compiles to C you can probably use it just about everywhere.
As far as android support this guy is working on adding support to android via Dalvik assembly. The usual approach to get nim to work with android would be JNI but that might cause problems for example with x86 android machines if I am not mistaken.
https://github.com/akavel/dali
I did one cross iOS/Android platform project using Kotlin/Native with its MPP plugin with reasonable success. However, this was 6 months ago and the JetBrains people surely haven‘t stopped moving forward.
Javascriptcore is a lightweight way to execute JavaScript on iOS and you can use V8 context or duktape on Android. This way you can also update code in your app without an app store update.
I think there is some confusion around this. You can use Javascript with iOS if you use Webkit + JavaScript Core, and ship all your features in the binary that your app uses.
2.5.2
"Apps should be self-contained in their bundles, and may not read or write data outside the designated container area, nor may they download, install, or execute code which introduces or changes features or functionality of the app, including other apps."
and
4.7
" your app must use WebKit and JavaScript Core to run third-party software and should not attempt to extend or expose native platform APIs to third-party software"
Perhaps your thinking about downloading such JS code at runtime from your servers, thus escaping Apple's control on the app, which was indeed forbidden (it is now ok as long as you don't drastically change the app)
Bundling JS in the app and running it has always been just fine.
Supporting a JS Engine is non-trivial. See React Native and Native Script. For example stacktraces etc.
With C++ in both Android Studio and X-Code you can put break points in the same IDE.
With JS you would use the browser to debug JS code, and Android Studio and X-Code to debug the native code. That split can be annoying.
I guess if the team that supports the JS engine is sufficiently large, i guess you can get more out shared JS code. The majority of the devs should be able to focus on JS development only.
And a couple of specialists deal with "JS engine issues".
I have great success using Kotlin Multiplatform to share code between iOS and Android. Have a look at my Android Jetpack Compose and iOS SwiftUI project sharing the common logic for a game https://github.com/SimonSchubert/Braincup
I've taken a contract first approach. Swagger / openapi for rest clients. Outside of that I use vertx which has bindings for almost every platform. With those two I can account for interoperability across all platforms.
C++ is first-class in Android via NDK. You can write directly to your app's memory from a C++ library without having go through FFI. I'm pretty sure it's the same for iOS but through a C ABI.
I want to like this answer but not sure it's true. Do you mean bridging ObjectiveC++ and Swift? Apple is now deprecating ObjectiveC++ (after all the work we went to to make it work back in the NeXT days).
I would like to integrate C++ code into a SwiftUI app but am not sure how to do it. Are there some iOS C++ APIs I'm overlooking?
Apple’s documentation for all sorts of things is in a sorry state lately. That includes mass “retiring” of perfectly good documentation for non-deprecated things with no replacement. I wouldn’t take missing or hard-to-find documentation for any specific thing as an indication that it’s deprecated. As far as I know, Objective-C++ is as supported as ever. That is to say, it’s not exactly a banner feature, but it works fine, and there’s no reason not to use it if it’s the best solution to your particular problem. I use it in a number of places, including to expose C++ code to Swift, which doesn’t interop directly with C++.
Picking on sibling comment, you can still reach for the document, all what is required is a little experience as Apple developer on how documentation get shifted around.
I’d be very surprised if this was true. Apple’s own frameworks are all C++ under the hood, e.g. CoreAnimation, AVFoundation, AutoLayout (part of UIKit and AppKit), Metal, etc. The meat of these frameworks is in C++ with an Objective-C++ layer on top, exposing an Objective-C (and thus Swift) API to developers.
A super thin layer made of C between say Objective-C or Swift and C++ is quite convenient though and doesn't add much of an security risk. See it as the lowest common denominator.
What’s the threat of a security vulnerability in a 3rd party mobile app that tightly sandboxes your app - especially for a none financial app? I would think that if even a vulnerable app could affect other running processes or the OS itself, you’ve found a vulnerability in the underlying OS.
And only their data in the app in question or any data that the user allowed the app to have would be vulnerable. If not, that’s an issue with the sandbox on the mobile OS.
If users care about their own data the best thing they could do is to stop using smart phones and signing up to google, facebook, saas providers etc. etc. They would leak your data with the efficiency any pirate will be jealous of.
How do you propose that an security vulnerability in an iOS app that doesn’t result in a jailbreak will allow someone to copy the app from an iOS device on to another device?
Also, are you claiming that using C == “not striving for quality” or that it is not “best practice” to use C?
And on a side note, most corporations don’t care about “quality” or “best practice”, they care about shipping and selling software. Two decades in the industry has shown that those two things aren’t as highly correlated as you wish.
Industry is young, but thankfully returning goods on app stores and suing companies for delivering bad software is starting to happen.
I am claiming both when using a language whose security reports from Google, Apple, Microsoft, ARM, Linux kernel just increase in size every year with the amount of memory corruption and UB induced security exploits.
Like those reports advise, usage of C should be constrained to environments where no other safer alternative is made available, or due to constraints on already deployed software.
Even the personal computer software business has been around almost 45 years if you count when Bill Gates was selling BASIC interpreters in the mid 70s.
What “safer” alternatives are better that give the performance needed, with tooling available and the cross platform requirements that the poster needs?
Also, you haven’t explained how a security vulnerability from a third party app can be “used for piracy”.
Where are all of the corporations that are being sued because of software quality and not using “best practices? I would say just the opposite, companies are being sued if anything for not meeting delivery dates.
The definition of enterprise software is basically poor quality software where the user is not the buyer and they have to work around bugs.
Can I please have some links to unbiased reports with real world data on how much damage is attributed to the use of C vs other languages? Not from the entities you mentioned as they all have their own agenda. Otherwise what you say sounds more like unsubstantiated FUD.
What “risk” is there in an overflow from using strncmp, strncpy, etc?
C++ still isn’t as easy to interop with other languages as C and the low level APIs built into operating systems are not going to use C++/STL and you still end up converting to standard C strings and arrays.
(It also always pads the full length with zeroes if necessary, so it's almost never what you actually want to do.)
The C standard library is full of these footguns.
I won't say C++ doesn't have its bad parts, and I certainly wouldn't say that it's impossible to avoid the bad parts of C (some would), but you probably aren't going to manage.
If all of your string manipulation is working with the knowledge of the maximum size, how is that any different than the standard Pascal or BSTR string handling where the size of the string can be found in the first two bytes of the string?
If you used the “n” equivalents, c would have 8 bytes and every other function would know to stop 8 bytes - assuming you always pass in a size parameter.
That might work - if you always use that pattern, and never, never deviate from it, including in all library functions that you ever call with your strings. That seems very brittle and error prone, though.
And why, when you have C++ strings that just handle all of that for you?
It's not. But plenty of other standard C functions like to use 0-terminated strings without explicit lengths, including most of the system interfaces, and others make it awkward to pass in the length that you're actually tracking. You only need to call one of those with an unterminated string and it doesn't even matter whether your code knows the string's length.
You could say that just means you have to be very careful whenever you pass a pointer to a string around without also passing in its length, but that's a lot of places.
C is pretty rudimentary for more complex logic - not having nice containers, things like std::thread or smart pointers can mean a lot of pain when trying to write code portable across platforms.
I don't think it's worth staying there - especially since C++ is a first party supported language on pretty much all platforms.
Can concur, we had huge success sharing our core business logic as a C++ library which was then used by UI on Android/iOS/Web and even desktop native apps.
Using Dropbox Djinni (https://github.com/dropbox/djinni) also helped with the horrible pain of JNI... although it's unmaintained these days. I guess people use SWiG now.
You might want to have a look at https://www.boden.io. Looks as if this might greatly simplify the task of sharing business logic (and UI if needed/desired).
I agree fully. Please consider that the Flutter team are having a hard time keeping up with iOS changes with regards to developer tooling. For example, print() is now broken due to iOS 13 in everything but xcode and while using a debugger/tests is the right solution, it sure is nice to be able to add a print() statement in there for quick and dirty...
So I'm sure lots of people will think that this definitely doesn't qualify as "Best language to share code...", but Haskell has stuff for getting web, desktop, iOS, and Android out of one code base. It's called Obelisk (https://github.com/obsidiansystems/obelisk) and it's actually getting to be a pretty good development experience.
I love hacker news. This is the comment I came here for.
Just use this : A language that is (at best) fringe on the platform you are using. Here's a toolset nobody has ever heard of. Now build your mission critical bit of infrastructure on this house of cards, wait for the toolset maintainers to be outpaced and under-resourced by underlying OS/platform changes and then have to rewrite the whole thing which if it doesn't kill your startup, will certainly massively impact its resources.
Well, developers are the kind of people that love to be contrarian, so it shouldn't be that surprising. Half the fun (in my mind) is doing something no one else is doing. Being novel. It's probably unwise in a business sense, but if everyone was being wise all the time, there wouldn't be much fun in software development.
You're not obligated to be a brutal capitalist as an engineer. It's okay to make decisions that are suboptimal (but still passable) for your employer but highly aligned with your own career interests.
If you always optimize for whichever company is employing you currently, you're doing yourself a disservice and essentially "leaving money on the table" :)
I'm not completely sure about your requirement, but as a game developer who uses Unity everyday, I would recommend it. Core graphics and UI components are available out of the box, and sometimes even when we need an app(nothing like a game) that need to access native APIs of the platform, we use Unity. It used C# as the default language, and platform-specific core logic can be separated within the code, using #directives so it's pretty straightforward.[edit: typo]
Something just crossed my mind while reading the question, that Swift could be a good candidate. Turns out there are compatibility layers that are based on Swift:
with the Adobe AIR runtime you will be able to publish to iOS, Android, Windows and macOS, see "Adobe AIR" [0]
ActionScript is something similar to TypeScript
you will have access to the whole Flash stack and more, see "Building Adobe AIR Applications" [1]
with ActionScript Native Extension (ANE) you will be able to add your native code with an easy to use AS3 interface, see "Extending Adobe AIR" [2] and "Using native extensions for Adobe AIR" [3]
Note, the latest Adobe AIR SDK are now maintained by Harman [4]
Since no one else has said it, I'll be the voice of reason.
Share your design specs only, and let each platform team write the implementation in the language that they think best.
Yes, you'll have two teams spending time on doing the same thing. However, you'll get important benefits.
Each team will be able to implement appropriately for their platform. While iPhones and Android phones are rather similar in terms of capability, the interaction models have a lot of differences, and forcing a common component often results in non-native feeling apps. Users will be at best confused, and at worst insulted by this.
Additionally, when you have two teams working on similar problems, they can help each other. Training on this interaction with things known to be pretty much the same helps people realize they can do it with things that aren't obvious. Meeting on a regular basis to discuss things that worked/didn't on the various platforms will help them all.
Users will be at best confused, and at worst insulted by this.
However... Don't assume that a user has an exclusive affinity with one platform at a time. Users will load the app on different phones, sometimes at the same time, so if there are any differences in the way the apps handle data you'll soon see things getting corrupted. Make sure you have lots, and lots, and LOTS of tests.
There are lots of internals that could/should be shared between apps. Recently relevant examples: a customized WebRTC stack, a websocket client with extra authentication and delivery rules.
FWIW, my take on this has been to embrace Conway's law: if you have enough shared work to form a team around it, then break off a c++/whatever library and a team to maintain it. But if the hope is just to save 200LOC here and there, just bite the bullet and write it twice.
Big thanks to whoever pointed out Kotlin Native: seems interesting enough to poke around with.
In this case they lost there C++ team, so following Conways law they went back to separate code based.
Also the open source C++ ecosystem has advanced quite a bit since when they did there project. You would be able to spend much more time on the problem domain, and zero time on writing a JSON library for example.
Having attempted this in the past let me say: I’m in violent agreement.
Attempting to “share code” between Swift/Kotlin is folly at this point. I’m not going to close the door on Kotlin Native some day. But for now just say, “No”.
I have a react native app published as part of our SaaS software suite. I don’t think users notice or even care if things feel marginally non-native.
I’d agree optimizing user experience by developing in native code might be important if you have a game or social media app where the worth of your company is directly correlated with your app install metrics.
Do you have any anecdotes or data that illustrates that users will be “confused” or “insulted” by non native apps?
Here's a Mozilla blog post about rewriting Firefox's Sync client code in Rust so the same code can be used on desktop, Android, and iOS. The FFI between the shared Rust code and C++, Java, and Swift app front ends is a little hairy but well encapsulated, generated code.
I'm surprised no one has pointed out the value of Ionic Framework (https://www.ionicframework.com). I'm a huge, huge proponent of this. TypeScript is a great language (in my opinion), UI code-sharing is inherent, and Capacitor (https://capacitor.ionicframework.com/) is great for all the native work you need to do. Worth noting you can do this in Angular, React, Vue, or pure JS.
You should share design specs between client teams and allow each of them to implement them within the parameters of what's expected on each platform. Don't force them to have the exact same UI at the cost of platform-specific idioms. It hurts customers on both platforms to take that approach.
Your business logic should be, to the maximum extent, implemented once on the server. Your client implementations should simply display what the server has computed, once. Caching it is fine, rendering it locally is fine for the most part, and you get a clean, well-fitted, elegant UI for it.
Any limited amounts of business logic that must be correct and truthful should be implemented as a Rust (or if you insist, a limited, well-defined subset of C++) library with C linkages and idiomatic wrappers for iOS and Android. If this can be shared with the server and/or web front-end (via emscripten for instance), it should be. It's usually painful to do this, but there's usually only a small part of your codebase that should fall under this section.
Xamarin (C#) and Cordova (JavaScript) are the usual suspects for such multiplatform endeavours. You should not use three languages in production if one is enough.
There's very limited appetite for introducing JavaScript on any client platforms. Your iOS app has to introduce a garbage collector, bridging, and yet another language that nobody on your team knows. Android has to spin up a second garbage collector.
C# has all the same problems for core logic, and is all fine and good but you can't really get a native enough interface out of it.
I have a similar use case where the crux of my business is really data / analytics centric. The user experience is pretty much limited to mostly information consumption with a few click events (favorites, like, dislike, delete and the occasional standard input forms).
I'm leaning towards using [Meteor](https://www.meteor.com/) to share code between mobile apps and web apps.
Using cordova shells is pretty neat for business applications. Would be interested in thoughts.
If you really want to optimize and share code across platforms, you should really go for C++.
Make your core logic in C++ and write bridges for Kotlin and Swift, where only the UI logic is involved.
C++ has the better ecosystem so far and the very modern standard (C++17) let you write robust code. There are also so many tools that help you catch errors and typos, plus thousands of libraries available.
In Readdle we use Swift as common language to run one codebase on all platforms. Currently, we use it for macOS, iOS and Android.
In Spark for Android almost everything except UI written in Swift
https://play.google.com/store/apps/details?id=com.readdle.sp...
FullStory is using Rust for our shared code, however the other sides are different: Java & Objective-C. It seems to be working pretty well for us so far.
Our requirements are probably a bit different than yours, though, because we're shipping a tool for app developers rather than the app itself. In particular, Objective-C was chosen over Swift because we didn't want to risk potential conflicts if our customers were using a different version of Swift and/or have to bundle a Swift runtime for older iOS versions.
Kotlin can generate both JVM bytecode and iOS binaries. I've successfully shared code between iOS and Android projects using Kotlin before. The overhead is quite low, and, all in all, I was quite satisfied with the results.
However, a lot of the tooling around this is experimental, so you might want to tread carefully here.
I do a lot of consulting for clients who use Embarcadero's Delphi to create native iOS and Android apps from a single source base.
Delphi is a commercial product, that comes with its price tag and there is, of course, a learning curve, but once you know the processes you can create great multi-platform mobile apps, with way less effort than having one team on Xcode and the other on Android Studio.
RAD Studio let's you build cross platform apps targeting Android, iOS, macOS, Windows, Linux, and HTML5 with a single codebase and single UI. Choose either Object Pascal or C++.
I prefer the Object Pascal side but the C++ side is also powerful because it solves some of the problems that the Dropbox team talked about in their "The (not so) hidden cost of sharing code between iOS and Android" article.
My team owns an Android (Kotlin) and iOS (Swift) app. The app is responsible for processing data, submitting to ML models, and then displaying results in a UI. We chose to do a lot of that processing in a shared Rust component. What we have found is a high overhead of bridging Kotlin/Swift to Rust. Some core logic has also seeped into our bridging code resulting in some duplication (exactly what we were trying to avoid).
With that, those of you who have found yourselves in similar situations, which language would you choose to be shared between your Android and iOS app (if any)?