Our budding (currently internal) API deals with building information models, originates in our main application written in c++.
There is a small implementation of it in C# for easy interop with other CAD software exposing .Net APIs (mainly just a class library with de/serialization). This also covers python scripting through python.net.
We reached a point where it would also be useful to have a small Typescript implementation as well for use in web-gl based in-browser viewer app. (We tried unity with our C# API, but the non-packing GC that comes with IL2CPP turned out to be a hard limit in our use case, runtime generating and regenerating huge meshes based on user input).
Now, for just the "class library" part code generation is doable, where we parse the c++ classes and autogenerate POCs in the other languages. This makes sure at least our representation of the data is in sync across all theatres.
Problem is, if we wish to lift some logic into the API libraries like validation, the parse and generate method complexity increases exponentially, especially through diverse languages like c++, c# and js.
I currently see 3 paths forward:
- Write the logic in only 1 language and hack it into the other environments (c++/il wrapper for C# and Emscripten for JS land). This works but introduces too many bottlenecks.
- Write the logic in some common easy to parse and sufficiently vague DSL from which it is easy to generate all 3 languages. I haven't found a good already existing solution to this, rolling our own seems prohibitively time consuming.
- Write the logic separately in all 3 languages utilizing each language to the fullest, ensure parity through rigorous testing with specification written in a common DSL (With something like Cucumber and Gherkin?) This is also time consuming, but we already spend time on testing which would be reallocated here.
What are the experiences with these strategies? Are there other major patterns for this?
Currently number 3 seems like the most promising, maybe because I have the least experience in it and of its pain points. Are there other / better frameworks for this than Cucumber/Gherkin?
EDIT: to elaborate on the architecture:
The main application is a big old windows desktop app (tightly coupled to mfc and all). In all API scenarios, communication is done through a binary file format. Eg.: in case of a .Net API call, the third party asks for the current model, which is serialized by the c++ code of our application, sent over through IPC to the .Net client, deserialized, modified by the client code, and serialized then sent back to the main application for evaluation.
All 3 API libraries would mainly deal with:
- Serialization / deserialization of this binary format (this in itself is the easy part)
- Provide class definitions to allow easy manipulation of the data in the target language (this is still not too bad with auto generated classes)
- Hopefully provide some basic "in situ" logic for the data in the target environment so the API libraries do not have to constantly communicate with the main software, this is what prompted this question. One such common logic would be validation, another might be preview mesh generation.
Re.: How does a browser based view fit? We have a prototype solution where our users can upload their models, and with a simple Unity WebGL viewer app they can be inspected in the browser. Our C# API library is used to understand the uploaded file, and generate preview objects based on it's contents running inside the browser. The user can also make some modifications in the webgl viewer, and ask for re-evaluation of the model where we spin up a VM in the cloud with our desktop app, load the modified model, calculate it, and send back the new recalculated model into the webgl viewer. This works, but is resource and time expensive, so the goal is to replicate the validation logic in our C# library itself so we can pre-emptively validate the model inside the user's webgl viewer for example.
null
pointer in one language, a special sentinel value in another, aMaybe
type in a third and a …Error
monads.