# Language-independent means of exporting program interfaces A thesis topic proposal by Bulat Khabirov, BS4-SE IU student. ## Introduction My name is Bulat Khabirov, I am a BS4-SE student at Innopolis University and an iOS developer. Software that I make is mostly client-server or standalone native applications. Often, these apps also have Android counterparts. Generally, every app's architecture can be divided into presentation logic (UI that the user interacts with) and everything else (that is, business logic, networking, persistent storage management, etc.). Many things from the latter part could be potentially shared across platforms, which will result in a more consistent codebase (one would not have to re-write same things for every platform), less errors and faster error resolve times (less code to fix and make errors in). The question is how exactly one would to it. One of the many ways to do it is to have a platform dependent part, that uses native platform APIs and is not shared, and platform independent part in a form of a shared library (or a set of libraries) that is reused across platforms. This is a technique that many services use, for example [Telegram](https://github.com/tdlib/td). With such an architecture a problem of programming language interoperability arises: platform-dependent part has to use a language, which native APIs are exposed to (Swift or Objective-C for iOS, Kotlin or Java for Android, C# for Windows, etc.). A shared part can use any language, that can run on desired platforms, but has to interoperate with other programming langues well, so that it will be simple enough to import such a library and justify the usage of such an architecture. ## The problem From my little overview of the current state of interopertaion of programming languages I concluded, that the most used means of exporting or importing an interface of a library are C headers (Rust, Go, Kotlin, Swift, etc.). And since C is a great but quite old programming language, C headers can not express many structures that modern languages have, thus limiting the level of possible interoperability and sometimes requiring to write a lot of "glue code". Some languages can use other tools: Kotlin and Swift support Objective-C headers, JVM languages can use JNI. These tools offer a much better level of interoperation, but are language dependent: one can not express more than Objective-C header supports while using it as means of exporting an interface, and same applies to JNI bindings. ## Proposed solution The idea is to develop a more expressive alternative to C headers, which will aim to support lexical constructs that are most common to modern languages: types, type members, interface declarations, more sophisticated enums, etc. At runtime, when the caller is in the host language and a callee is in the guest language, the idea is for the host language runtime to pass the call to guest langague runtime, just like Swift and Kotlin do it with the ObjC runtime, where usage of ObjC's `NSString` class: ```swift // Swift code let string = NSString(withFormat: "abc") let isEqual = string.isEqual(to: "def") // calling NSString's method ``` is interpreted as two [objc_msgSend](https://developer.apple.com/documentation/objectivec/1456712-objc_msgsend) calls from [libobjc](https://developer.apple.com/documentation/objectivec/objective-c_runtime?language=objc), since `NSString` is implemented in Objective-C and it is its runtime's job to message `initWithFormat` and `isEqualToString` calls to the correct receiver `string`. This way the interface I am proposing is kept simple and leaves the hard work to the programming languages themselves. ### Requirements for a langauge to support the proposed interface #### 1. Ability to import and export a library interface in a certain format A language may choose to selectively import and export declarations from and to the interface file. If a feature is too language specific and can't be expressed via the interface, it can be ignored. For example, Swift only exports types and methods marked with `@objc` annotation to Objective-C, thus making it explicit for the programmers that the method dispatch will be done using ObjC runtime, and not via Swift's vtables or static dispatch: ```swift // --- Swift code // Structs are value types that are not supported in // Objective-C and won't be exported to the ObjC header. // Marking it with @objc will result in a compile time error. struct MyValueType { ... } // Since MyClass explicitly inherits NSObject (ObjC) it is // implicitly @objc class MyClass: NSObject { func doSomething() { ... } // won't be visible in ObjC @objc func doSomethingElse() { ... } // will be exposed to ObjC } ``` Similarly, when importing the interface a language may choose not to import unsupported constructs, while successfully importing supported ones, if possible. When possible, it is preferably a compiler's job to warn that some features declared in the interface. #### 2. Open and standartized language runtime APIs that other runtimes could use to forward calls As described above on the example of usage ObjC types in Swift, a host language must be able to refer to guest language runtime. Kotlin/Native and Swift use open ObjC runtime to interoperate with Objective-C. If such mechanism can be made language independent and standartized, it will allow any language to talk to any other language without knowing exactly what language that is. ## Roadmap 1. Attempt to manually import, use and link types and their members from a library, written in language A to a program written in a language B (proof of concept) 2. Develop a very simple but extensible first version of an interface format, that will be used by languages to import and export their interfaces 3. Extend some two existing open source languages to support the developed interface ## Desired outcomes 1. Initial version of the interface format that supports **at least** simple type declarations with support for type members (simple methods and properties) 2. A fork of existing open source language compiler extended to support the aforementioned interface, that is, being able to export and import libraries with the interface exported in the developed format, and then compile into a working binary.