Introduction
My name is Eric Wing and we’re going to talk about Swift on Android.
Why Swift on Android?
I want to assume everybody can imagine useful cases for having a cross-platform native language like Swift available on Android. I’m using the real Apple Swift. If you’ve heard of the RIM object Silver Swift, this is not that. I’ve given talks about Android before and I’m brutally honest about Android. While the experienced Android developers always thank me at the the end for telling it as it is, people who are not familiar with Android development are in disbelief about how bad things can be and start to question my credentials.
My Background: Worn lots of hats
I’m not just an Android developer but a Cocoa developer, and I’m trying to bridge the words for the audience. I worked on a global satellite communication system called Globalstar (e.g. launching satellites into space with rockets!).
I worked in cross-platform development during the end of the Unix wars and the peak of the Microsoft monopoly. Scientific Visualization was a specialization I had. At the time, certain engineering niches needed higher liability and Windows was too unstable, but all the Unix vendors are dying. Then a solution came with Mac OS X, which promised as real Unix combined with a good GUI. Eventually, my work shifted from porting to Mac to embracing Cocoa to create first class UIS deeply integrated with OpenGL visualization systems.
I got involved in open source projects. It usually related to improving Apple platform support. SDL is the ultimate cross-platform foundation layer used heavily by the video game industry. It provides access to the graphics system, audio, input events, and anything you need to create a game or multimedia app. If you’ve played a cross-platform triple-A game in the past 15 years, it is better than a coin flip that uses SDL. Valve Steam has adopted SDL as a foundational component, it’s important to the video game industry. CMake is a cross-platform meta build system. You list the files that you need to build in a text file, and CMake will create native projects for it like Visual Studio, X Code and Make Files.
I wrote the world’s first full featured bridge between the Lua language and Cocoa. I’ve used many low-level parts of the eject and see runtime that most people don’t even know exists. I understand language bridging.
I coauthored the book Beginning iPhone Games Development, published by Apress.
I worked on some commercial game engines. I was the chief architect of the Corona SDK, which allowed people to write native cross-platform games in Lua. I later co-founded Lanica to build a game engine for accelerator people could write native cross-platform games in JavaScript. Since Android development has many problems, I inadvertently became an Android expert out of necessity.
As far as I know, I was the first to create a proper Swift Android app - February 27, 2016.
Ouroboros: Eternal cycle of life & death. What’s old is new again
Ouroboros is an ancient symbol of a serpent or a dragon eating itself. It represents an infinite cycle or something constantly recreating itself. With this talk, I hope to give you much more than a checklist of things to do. I want you to see the fundamental concepts that allow everything to work. Nothing here is new. We are reapplying old concepts in slightly different ways, when we talk about the Swift Compiler in native code, think about C compilers in native code. When we talk about Android, think about Unix and Linux. Seeing these analogies may help you understand how everything works.
The most important fundamental that keeps reappearing in this talk is C. C makes everything possible. C is like the building block for everything else because it has special properties. C is the most portable language. Every platform has a C compiler, even the web has a C compiler now. The C ABI is stable and everything is built on top of it. Almost all languages have a way to talk to C. Swift in particular, has one of the best. There is software written in C, which all the other languages can use because they all know how to talk to C.
Language vs. Libraries
When we talk about using Swift on Android or any other language for that matter, it is helpful to separate the difference between the language and the libraries because when I talk about using Swift on Android, I do not mean using UIkit on Android. UIkit is a library and one that is unlikely to ever be reported to Android, I’m talking about the language.
There is this fuzzy area with the Swift standard library base, which I boxed in yellow. You can see there are multiple libraries. Swift Core is the only one I call essential. It contains definitions for basic types we take for granted like int, and I believe it contains the Swift runtime. The others are more optional. I want to emphasize that we are getting the base Swift language working on Android and you don’t need the rest to make fully capable, shippable apps with Swift.
Here’s an example. Imagine these apps are written in Swift and all you must use Swift Core, but after that, each uses a different set of libraries. At the top is our native iOS app. It uses all the Swift standard libraries plus Uikit and Core Audio. Next, consider a native Android app written in Swift. This app uses the Swift C standard library, but there is no Uikit or Core Audio on Android, for native Android, we would use the Android SDK and OpenSL ES.
Finally, consider a native cross-platform game that goes to a whole bunch of platforms beyond Apple and Android written in Swift. SDL provides us all the functionality we need. SDL even provides audio, but for symmetry, I decided to include OpenAL for 3D Audio.
App Development vs. Server Development
I care about making shippable user facing apps that would be deployed on an app store, not command line server apps. As Mac and iOS developers, you know what I’m talking about: we must do extra things that other don’t. All our resources and dependencies must be deployed with the app. We can’t require users to install things. End users can’t be expect to compile apps from Source.
I bring this up because these are the official instructions for using Swift on Android. There are four steps here. The last two steps are completely wrong (see video) because they’re trying to build a Command line up and install it and run it on Android. You iOS developers should be able to imagine how pointless and useless this is. It masks a whole class of bugs because the environment and conditions this runs in is not like the normal Android environment, we’re going to do things the right way. But first, I must introduce Android development.
Android NDK (Native Development Kit)
All real Android apps must be written using the Android SDK, which is in Java. Android originally was Java only, but had to cave to game developers, they created the NDK, which lets developers create dynamic libraries in C and C++, but the NDK is the bare minimum they needed to do. You still must create a normal Android SDK app and start in Java. You must use Java’s loan library to load the native dynamic libraries and then use Java JNI to cross between languages. You might be asking how Swift fits in.
While the NDK was intended for C and C++, it is for all things related to native code and Swift generates native code. There is nothing new here; old concepts reapplied in a slightly different way.
Swift becomes our stand-in for C and C++. Unfortunately, the Android NDK is awful. Legendary game developer John Carmack of Doom and Quake fame called it “half-baked” and says “It really does suck.” People like to remind me that Carmack has rarely complained about developer environments, even ones that are notoriously famous for being hard, such as the Sega Saturn. This is damning, but this quote went viral because every NDK developer knows this pain. The NDK is a second-class citizen on Android with poor integration. The word on the street used to be that Google only has two full-time engineers working on the NDK.
Why am I getting on Google’s case? Android is eight years old. They’ve ignored our pleas, but reports go into the void. Public ridicule is the only tool we have left. This is one of the riches, most powerful companies in the world with complete market share dominance dominance in mobile. It is shameful, it is bad. I want to give you a taste of what it’s like you’re prepared.
Bionic (Android’s C standard library)
Android does not use glibc. They wrote their own standard C library for Android called Bionic. It doesn’t care about POSIX compliance. It doesn’t even care about ANSI compliance and eight years in Android, it is still terrible.
Lua is an embeddable scripting language. It is renowned for how portable and clean its code base is. Lua has been built on everything. It doesn’t resort to pound dip dash everywhere for different platforms. It is a singular code base written in pure standards compliant ANSI C. To demonstrate how awesome the code base is, somebody build modern day Lua in Boroland Turbo C 1.0 for MS-DOS from 1990 without modifying the source. It built and ran successfully.
If we try this with a modern Android NDK we get build failure. This is a post from a Bionic engineer. I’m not picking on this engineer. This poor soul is trying to fix this mess, but this gives different insights into why Android is awful.
Let me read an excerpt: “As you may be aware, Android’s C library, Bionic, is a hybrid of code from different sources, home grown, FreeBSD, NetBSD, and OpenBSd. NetBSD files aren’t from a single NetBSD release. hell, they’re not necessarily from any release. I found the bug that had been fixed in Upstream in like, 1996, but we had some random old version of that file.”
Terrible performance bug for strlcpy
In a prior project, I wrote a program to run a JavaScript performance to suite called Test262, which goes through 11,000-plus files. I use strlcpy in a hotspot. For a hot loop that should have taken 14 milliseconds, it took 9,000 milliseconds.
On the SDK side, I was trying to get my list of 11,000 files inside a directory in the APK. Little did I know, I walked right into a well-known Android performance bug. Pessimistically, this should take no more than a few seconds. Three hours later, I gave up and killed the process.
Speaking of files, files that ship with your app are inside the .ap. Think of it as a zip file. You can’t use the standard C library file functions like fopen
and fread
on anything in the .apk. Google makes you use a different set of functions. On top of that, they require a parameter that comes from a “God” object from the Java Android Activity or Context class. This means existing cross-platform libraries won’t work without special modification for Android. How many projects want to do this? And it’s ridiculous that this problem even exists.
Dynamic Library System wonky too
Android has wonky behavioral rules for dynamic libraries. I wish I had time to cover this in detail because things are affected by this. It is a common source of breakage and often leads to needing to specially modify cross-platform code.
Another example I’m going to call out is the soname. Soname is a meta data field and dynamic libraries for the Elf Executable and Linker format, which is used on Linux systems and much all Unix systems except Apple. There is a strong convention that put versioning information in the soname on Linux distributions combined with a series of symlinks. This will break on Android. You need to go one step deeper: C++.
Swift & C++ (and how it affects you)
Once upon a time, it was well known that you do not write libraries in C++, but I see a lack of library developers giving talks nowadays, and people seem to be forgetting these important lessons. I have to mention this because Swift uses C++. Swift itself is implemented in C++ and the standard libraries depend on the standard C++ library. Thus, the C++ fitpals are passed onto you. With the adnroid NDK, these problems are much more apparent.
Android NDK and C++
The NDK provides five difference C++ standard libraries you have to choose from. Choice is not a good thing. All are incompatible with each other. The C++ standard library does not guarantee a stable ABI, ever NDK upgrade potentially breaks things. If you use dynamic linking for your shared library of choice, you must bundle it with your app because Android does not ship a copy with the OS. This is in contrast to Apple, which ships you one to spare you this mess.
In the real world, people build library binaries and share them. But people don’t upgrade their NDKs all at the same time, and versions get mixed. People use multiple libraries and each library could be built with a different NDK version. You’d expect that the final application must include a copy of all these different C++ standard library versions that all your different libraries depend on. But Android doesn’t name versions differently, and files will override each other. Some of your libraries will start calling into the wrong version and bad things happen.
In contrast, Microsoft Visual Studio has the common sense to put version numbers in the file name to avoid this problem. we should statically link. This is the warning that Android has in their documentation about static linking. It’s loose. Thanks for nothing, Google. In practice, I personally found static linking to be the better of the two. Unfortunately, modifying this with build system is hard. I’ve successfully modified it in Swift 2 and submitted a patch, but the patch was never incorporated and somebody upstream re-based, the patch is broken now. It’s back to dynamic linking for now.
Let’s build Swift for Android: Dependency hell
We are application developers. The Android NDK provides almost no libraries we are responsible for building every library we need and shipping it with our app.
I showed these instructions earlier and said this mostly works. But you need to know about this gotcha. This is an Android variation of “DLL hell”. The main dependency for Swift Core that we need is libICU, the international components for unicode library, which is written in C++.
ICU is a popular enough library that Android manufacturers or Android itself may use internally. If used, when we try to load our ICU library with load library, the call silently does nothing because the operating system thinks it’s already loaded. If we use the exact same version of ICU with the same build options, things will work, but ICU is notorious for breaking compatibility every version. Throw in Android fragmentation, and it is guaranteed that somebody will be running with a different version.
Now that the versions don’t match, when your code uses ICU, bad things start to happen. If you’re lucky, you’ll get a crash. One way round this is statically link with ICU. But, if you must dynamically link, you should rename the libraries and the symbol names they do not conflict with the version in the operating system. ICU has switches to help mangle names differently because they are at least aware of the problems caused by breaking compatibility all of the time. You need to disable soname versioning because libIC’s build system is overly aggressive about setting it. good news.
Let’s use Swift on Android!
If we made it this far, we have a perfectly usable Swift for Android. Unfortunately, I need to skip foundation for time. It’s not part of the official build yet, but this slide has a few notes on its dependencies.
Earlier I said the official instructions were wrong. We’re going to do it the right way. Remember, all Android apps must use the Android SDK, which is in Java. We need to start in Java and work our way to Swift. We need to create a proper Android Java app and follow the standard techniques to cross into the NDK. We’re going to start in Java, cross into C, and then cross into Swift.
Android/Java
We start in Java. On Android, every Android app must have an activity to start in. An activity is like a window or a view controller. I made this class my starting activity. I’m using the on create method as my starting point. You can think of it as a knit and Cocoa.
public class MyLaunchActivity extends Activity {
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Note: Order matters!
System.loadLibrary("c++_shared"); // (if we didn't compile statically)
// Notice that I renamed the ICU libraries & symbols
System.loadLibrary(“icudataswift");
System.loadLibrary("icuucswift");
System.loadLibrary("icui18nswift");
System.loadLibrary("swiftSwiftOnoneSupport"); // used by swiftCore
System.loadLibrary("swiftCore");
System.loadLibrary("swiftGlibc"); // Should be named Bionic
// System.loadLibrary("dispatch");
// System.loadLibrary(“Foundation"); // (may have additional dependencies)
// This is our Swift code compiled into a dynamic library
System.loadLibrary("MySwiftMainProgram");
Here we must load all dynamic libraries for Swift. Order matters, we load all the dependencies first, then Swift itself, and then our program, which we wrote in Swift.
package com.blurrrsdk.app;
public class MyLaunchActivity extends Activity {
// Tells Java/JNI we promise to implement this function in native code
// Activity is unused in this example, but useful as ‘God’ object
public native void MyMainEntry(Activity activity);
@Override
protected void onStart() {
super.onStart();
// Call into native code
MyMainEntry(this);
}
}
Remember, we cannot build normal X cable files for Android, everything we write must be built into a dynamic library it can be called from Java. This is the same class as before, but I’ve hidden the on create method we can see this. On start is roughly the equivalent to awake from NIB or applications that finished launching. In here, we want to call a native function that will get us to C. The mechanism that makes this work is Java JNI. JNI is well-documented, it comes down to following a bunch of rules and boilerplate. In this example, I’ve declared that I promise to implement the function called MyMainEntry in C. The native keyword tells Java that this will be a native function.
The Java compiler is now trusting me to fulfill my promise of implementing it. I want to point out the package name declaration here because you will see how it is used in a second.
Now in C: call into swift
This is the implementation for that native function. Notice that the package name is part of the function name. This is one of those rules of JNI.
#include <jni.h>
// Promise C we've implemented this function.
extern void MyMain(void);
JNIEXPORT void JNICALL
Java_com_blurrrsdk_MyLaunchActivity_MyMainEntry(
JNIEnv* jni_env, jobject thiz, jobject activity)
{
// Call into Swift
MyMain();
}
Now that we are in C, we need to call into Swift. I’m going to do a trick, but it’s a trick based on old fundamentals. Let’s call a function that looks like a C function but is a Swift function behind the scenes. We’ll call it MyMain().
Finally, we’re in Swift and here’s my Swift function. The trick is, the app’s _cdecl
parameter. This tells the Swift compiler to make the function you see call in conventions it can be called like any other C function. Notice we declare the function as public. Make sure the symbol is accessible to be called across the dynamic library boundary. We transformed and reduced the problem so it looks like C. Again, there is nothing new here. We took our Swift ideas and transformed it to look like how we would solve it with C in the past. Now that we’re in Swift, we can start having fun and write things in Swift.
@_cdecl("MyMain")
public func MyMain()
{
// Now the fun can begin!
// <Your Swift code starts here ...>
let four = 2 + 2
// TODO/FIXME: print goes to /dev/null on Android
print("2 + 2 = \(four)”)
// Remember to not block the event loop
}
We must never block the event loop. Android is event-driven, like iOS. You will need to figure out how you want to use Swift in your app. You’ll likely create more callbacks like this to call Swift for different events. Alternatively, you could spin off the background thread. However, I strongly discourage this unless you know exactly what you’re in for. If you ever need to call system APIs from Swift, you’re in for a world of pain from doing it from a background thread. This is like trying to write a full-feature Cocoa app from a background thread: you are asking for trouble.
Caveats
There’s no objective C runtime on Android. Also, be extremely careful about the initialization of static and global variables. In Android, these variables may not get re-initialized on subsequent launches. In this example, I have a global variable called g_isInit
. It is initialized to false. You can see when we first run this program, the top block in the with else gets run because our variable is false. We then set that variable to true. In Android, let’s assume you exit the program with the back button, which is an Android difference compared to iOS.
Let’s relaunch the program. Depending on whether Android purged all the NDK memory between runs or not, our goal variable may or may not get reinitialized. If Android let this memory alone, when you relaunch the program, the dynamic library you loaded is still in memory. Google made the decision to not reload and reinitialize things. In this case, even though this is a brand new start, our global variable is still set the true from the last run. If we take the bottom block of the with else, we will take the bottom block, which is probably not what we are expecting and wrong.
This problem scares me the most because it is subtle and I don’t know how far reaching the implications of this are yet. If you need this pattern, try to design it in a way you can explicitly reinitialize your variables manually at start.
Build Systems (Ugh…)
As somebody who has done cross-platform work, this tweet resonates with me “when you’re trying to ship on 3 platforms, you’re dealing with portability issues. But on 13 platforms, it’s all about build issues”, by Fabian Giesen.
Even at three different enough platforms, the build system differences are crippling. Take X Code, Android Studio, and Visual Studio as three of them. They’re completely alien to one another.
Build systems are the worst. While languages are standardized and cross-platform at least try to minimize the differences, build systems are completely different and the platform vendors have no interest in minimizing the cross-platform pain.
Build System Options
There are three basic techniques to build your projects for Android:
- Swift Package Manager. Personally, I haven’t found this useful. The main problem is that things we need to do with Android Studio are a far cry from what Swift Package Manager does.
- You can string together the cause to the Swift compiler to build everything yourself. Look at what XCode does and reproduce the commands. Obviously, this is a pain and it’s hard to scale, especially as you need to maintain additional platforms.
- CMake.
CMake is well-used by cross-platform projects, even LLVM, Cland, and Swift are using CMake internally. Surprisingly, Android recent announced their support in CMake as part of Android Studio. CMake already has support for each platform’s native build process. For example, it can generate Esco projects. But since Swift is a new language, CMake doesn’t know anything about it. I started implementing support for it. My repo’s on Get Hub if you’d like to help. It’s a work in progress, but there is enough to make shippable applications.
cmake_minimum_required(VERSION 3.4)
project(MySwiftProject C Swift)
if(ANDROID)
# Must build library on Android
add_library( SwiftApp CCode.c SwiftCode.swift)
else()
add_executable(SwiftApp CCode.c SwiftCode.swift main.swift)
endif()
set_property(TARGET SwiftApp PROPERTY SWIFT_BRIDGING_HEADER "MyBridgingHeader.h")
This is a simple CMake script showing how to make a library or executable for Swift code. CMake script isn’t going to win any beauty awards, but the CMake project generation capabilities are unparalleled.
Let’s talk about Libraries for writing Android apps
There are three major categories:
- Native Android-only development in Swift
- Cross-platform development (non-native GUI)
- Cross-platform native GUI
Native Android in Swift
Can we write native Android-only apps in Swift? Yes, but it isn’t pleasant. We must go through JNI. Furthermore, not everything is possible through JNI. For example, you cannot subclass through JNI, you’ll still need the right Java for those cases, unless you resort by code hacks or code generation.
But again, there’s nothing new. JNI has been around for a long time. We know how to deal with it, and the world has come up with all sorts of solutions. But they all come down to the same basic ideas. You can write higher level libraries to encapsulate and hide all the JNI so when you use the libraries, you don’t have to touch JNI. Or, you can develop co-generation tools. While I’m not a huge fan of co-generation because it often introduces new problems (e.g. complex build systems, long build times, and application bloat), you can see high-profile companies have resorted to this on Android.
Cross-platform (C) libraries
Moving beyond pure native Android, let’s look at cross-platform libraries. Again, there’s nothing new. This has been solved many times over. Developers have been doing cross-platform for decades, especially by the video game industry. There’s a C library for everything. And, if there’s a C library, we can use it with Swift.
Here’s a list of the some of the usual suspects: SDL, OpenGL, OpenAL, FreType does fonts, libpng and libjpeg for your image needs, cURL for networking. Chipmunk even provides a physics engine in PureC.
FlappyBlurrr Swift
There’s already more than enough to make full apps in Swift on Android and any other platform you can think of. This is a FlappyBlurrr clone I wrote in Swift using SDL and company.
I’m a FlappyBlurrr perfectionist and most clones are terrible, I focused to get the timing details right (even though I don’t have time to prove it to you). And because our libraries already work cross-platform to everywhere, this program can work everywhere. This even runs hat a smooth 60 frames per second on a Raspberry Pi.
What about (non-native) GUI?
Let’s start easy with non-native GUIs, ones that display the exact same thing no matter what platform you’re on. My favorite is Nuklear. It is pure C, it can be used easily with Swift, and it has zero dependencies, it is easy to drop into a project. It is designed to be easy to adapt to any drawing toolkit. OpenGL is the most common, but it can be adapted to anything.
Here’s a screenshot, and a nice view of it running on Android (see video). This is a particle designer I wrote for the desktop. One aspect I wanted to not is that these non-native GUIs scale linearly with your screen size. I intentionally made the widget small I could fit more, my design is not ideal on a phone. But, it does work and it is surprisingly usable on an iPad or Android tablet. I’m showing this to you to get you to think about your designs if you need to support a wide range of screens, like TVs to phones.
What about cross-platform native GUI?
But I know most of you are native developers. We know how much the native experience can matter to users, and how much better it can be. Is there a cross-platform solution to native GUI?
I know everyone here wishes they could take their Cocoa apps and recompile them everywhere else, but this is a hard problem. If you look at history, there is a long list of serious attempts. Every one of these has failed to achieve the dream. If we look beyond Cocoa, we see that there are very few actual native toolkits out there, and the ones that we can use with Swift are even fewer. But there is one I like, called IUP.
IUP (Portable User Interface), A Hidden Gem
IUP originated as a research project from the same university in Brazil that created the Lua language, but it has since become a production-quality library used in certain circles like the oil industry and scientific visualization.
It uses true native widgets. It is small and focused only on GUI. Most other libraries have become a massive kitchen sink, reinventing everything and has tons of bloat. For us, this is a perfect fit because foundation + IUP has no overlap, like foundation + UIkit.
It is written in C, but it is written with language bindings in mind, we can easily use IUP in Swift. It also comes with a textual layout description language called LED, separating code from data, and can be used for per-platform customized layouts.
IUP’s research roots were focused on how to deal with the wide variations between different platforms not only in the widget differences, but on how not all platforms use object-oriented languages. It is very well thought out. Much of the API solution centers around a key value attribute system. Think NS user defaults. This allows API access to native features that may not exist on other all-platforms without constantly breaking the API design, nor preventing you from accessing platform-specific features if you want them.
Squint hard and see…
While some people may not be able to look past the stringy API, this is protocol-oriented design. At least this best can be done within C’s weak type system. I think there are amazing possibilities for a Swift wrapper for IUP. There’s already been talk in the Swift community about what if we could have a GUI API designed around protocol-oriented design.
Here’s a hidden gem that needs polish. And the great news is that the Swift community has already developed many techniques to build nice wrappers. For example, last year’s Try a Swift talk, Swift Eye for the Stringly Typed API by Andy Hope.
IUP drawbacks
But every solution has its drawbacks. For IUP, it has native windows, GTK2, GTK3, and Motif, but no Cocoa. But we can fix this.
This is a screenshot from a Rio program I wrote (see video). The screenshots are from Windows and Linux. This is a work in progress, but here it is, running on Mac.
What about mobile? We can fix that, too. IUP is well-designed. I believe it can do mobile, too. You can look up a YouTube presentation I made on this topic. As a simple example, most other libraries made the mistake of modeling their APIs off of existing desktop APIs and everything is shoehorned into that, and we get things like a Window API. In contrast, IUP created a more ambiguous dialogue API. On the desktop, this may map to an actual Window API. On mobile, we get to decide what makes sense. For iOS, we map dialogue to use UI navigation controller and view controllers, and on Android, we map it to activities.
Demo Program: Create Dialog & Button (recursive)
var g_buttonCounter = 0;
func BlurrrMain() -> Int32 {
IupOpen(nil, nil)
IupSetFunction("ENTRY_POINT", IupEntryPoint);
IupMainLoop()
return 0;
}
func IupEntryPoint(_ ih:OpaquePointer?) -> Int32 {
g_buttonCounter = 0
return ShowNewDialogCallback(nil)
}
func ShowNewDialogCallback(_ ih:OpaquePointer?) -> Int32 {
let button = IupButton(nil, nil)
IupSetStrAttribute(button, "TITLE", "Iup Button \(g_buttonCounter)")
IupSetCallback(button, "ACTION", ShowNewDialogCallback)
let dialog = IupDialog(button)
IupSetAttribute(dialog, "SIZE", "QUARTERxQUARTER")
IupSetStrAttribute(dialog, "TITLE", "Iup Dialog \(g_buttonCounter)")
IupShow(dialog)
g_buttonCounter += 1
return IUP_DEFAULT
}
You don’t need to understand this code, but I want you to know that this is a complete IUP program written in Swift. For clarity, I did not write any high-level Swift wrappers, you are seeing everything. This program creates a dialogue containing a button. When you press the button, it creates a new dialogue with a button and forth.
See the video to see the program running on Ubuntu Linux, Raspberry Pi, Mac, iOS. We are mapping dialogue to use UI Navigation Controller and UI View Controllers under the hood. And finally, Android. Here we map dialogue to activity. And… Surprise! Swift on Windows.
Re-cap of what we just saw
You saw native GUI cross-platform desktop and mobile with a single code base in Swift. If you’d like to help out, my research are in GitHub.
IUP development links
-
My repos https://github.com/ewmailing/IupCocoa https://github.com/ewmailing/IupCocoaTouch https://github.com/ewmailing/IupAndroid https://github.com/ewmailing/IupEmscripten
Blurrr SDK (My current endeavor)
There is no magic in cross-platform, but there is tedious work involved. I’d like to make cross-platform native development more accessible to more people. I created Blurrr SDK. I want you to leverage my experience in dealing with all the annoying platforms specific to the differences you can focus on your core program. I use Blurrr to help me create all the examples in this presentation.
Blurrr handles the build system challenges using CMake under the hood. Blurrr provides a bunch of deployment-ready pre-built libraries so you can build your app and ship it. I tried to provide a download and go experience for Blurrr itself.
This is the Blurrr workflow (see video). Start it up, open your project, then you get the appropriate native project for the platform you’re on. Then you work on your code, build and run. Currently, I include libraries, like SDL. Blurrr is currently best for games and multimedia apps.
I am very serious about IUP. It is in development but quite capable. I’m still nervous, but I want people to use this, I’m opening up the beta today you can all start playing with it. I’m still trying to get off the ground, I could use your support. I will be doing a game workshop at the Hackathon.
Carlos M. Icaza, June 5, 1966 - May 17, 2016
I want to switch gears and say a few words about my friend, mentor, and former co-founder, Carlos Icaza. He passed away unexpectedly this summer. While he was known by many different groups for different accomplishments, the Swift community knows him as @codinginswift, with 18,000 followers. He held Swift meetups. This one (see video) was in Silicon Valley; he even managed to somehow get the elusive Chris Lattner to show up that night.
So…
I wanted to try to write something in his memory that would have a special significance for events we shared together. In some sense, this is a bucket list of things we wanted to achieve together, but time ran out. For example, he was an expert at splines. We wanted to do a spline project together, but it could never get a high enough priority.
I wanted to leave you with something that inspires you with how much is already possible with cross-platform Swift today.
Q & A
Q: How that is Apple in these respects, in the same fragmentation and not following standards? Eric: It’s good. Our rules from generally, and all the companies I’ve worked with, Android is about four to 10 times harder.
Q: How about the memory management difference between Android platform and Swift? Eric: If you’re on Swift, you’re using the NDK side of the memory, not the SDK side unless you’re calling in to native widgets. The funny thing about Android memory management is that the Java side is completely managed and Google has done stupid things and they have imposed artificial memory elements for your Java apps. A long time ago, the memory limits were artificially, insanely low and nobody could write real apps with it, the NDK people figured out if you do stuff on the NDK side, you can use all the memory that’s on the device and those limits don’t apply to you. And because Android is bloated and general, they ship with more RAM than their iOS device. you actually, generally, get more memory with Android than you do with iOS.
Receive news and updates from Realm straight to your inbox