jbhoot / poc-ocaml-logic-native-ui

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

This is a work-in-progress experiment to probe the viability of using OCaml for the core of a desktop app, and a platform-native UI (which is Swift on macOS for this PoC) wrapper.

The PoC compiles a Swift executable which also bundles in an OCaml library.

Rationale and Goals

Right now, all the PoC does is generate a Swift CLI app which passes a protobuf message to OCaml, which in turn returns a protobuf response, which is printed to the terminal.

My vision is that Swift and OCaml talk to each other asynchronously through message passing via a protobuf bridge. This approach should keep the C interop code to a minimum of a couple of functions - one that sends messages from Swift to OCaml, another that handles the other direction.

So far, I have only managed to implement a synchronous mode of communication, i.e., a function that Swift calls and gets a return value from the same call. This might prove expensive if OCaml were to do some complex operation. I believe an asynchronous approach is the better way, but I am yet to get there.

All of the above assumes that the Swift side is the main driver of the whole setup, the OCaml library being the passive side.

Another reason to adopt the message passing apporach is so that the Swift side has the option to carry out all the I/O operations - UI, network calls, may be file or DB ops too. This flexibility could mean that on a resource-sensitive platform like iOS or Android, native I/O operations could be used, which are often optimised to a maximum w.r.t resource usage. Though there is also the question that what the hell is left for the OCaml library to do in this scenario. I will think about it when I get there.

Over all, the viability of this approach depends on how thick the OCaml core can be. Thinner it is, less it justifies all the gymnastics.

TODO

Process

# Install ocamlfind and ocaml-protoc in local opam switch
$ opam install ocamlfind ocaml-protoc

# $ ocamlopt -output-obj -o modcaml.o mod.ml        
# ld: warning: /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libSystem.tbd, ignoring unexpected dylib text stub file

# Ensure that the ocamlfind being used belongs to the same local switch, and does not point to a global installation.
# Otherwise ocamlfind won't be able to locate the packages installed in the local opam switch.
# .mli comes before their .ml counterparts.
ocamlfind ocamlopt -output-obj -o modcaml.o -linkpkg -package pbrt messages_types.mli messages_types.ml messages_pb.mli messages_pb.ml mod.ml
ocamlopt -c modwrap.c    

# cp `ocamlopt -where`/libasmrun.a mod.a && chmod +w mod.a
cp (ocamlopt -where)/libasmrun.a mod.a && chmod +w mod.a

ar r mod.a modcaml.o modwrap.o        

# cc -o prog -I `ocamlc -where` main.c mod.a -lcurses        
cc -o prog -I (ocamlc -where) main.c mod.a -lcurses        

$ rm -rf macos/ModKit.xcframework 

$ xcodebuild -create-xcframework -library mod.a -headers include -output macos/ModKit.xcframework


# Generate .pb.swift in current folder
$ protoc --swift_out=. my.proto

About


Languages

Language:Swift 42.6%Language:C 26.8%Language:OCaml 26.3%Language:Shell 4.3%