Creating an OCaml binding to LXC, seeking advice on API design

Hello everyone,

(I hope I’m asking at the right place.)

I am currently creating an OCaml binding to LXC C API, and have completed the low level API layer.

But a bit uncertain about how to move forward with the high level API design.

Is it advisable to follow/mirror go-lxc’s high level design?

Specifically has there been any major criticisms toward the go-lxc that warrant any high level API change, or things that I should be aware of etc.

Thanks very much for your time!

We’ve not really had much of an issue with the Go one.
The main problems we ran into were around refcounting so the container struct itself gets freeed when the Go struct is no longer in use.

Most of the bindings for liblxc tend to be pretty low level with very limited abstraction.
Go-lxc has some basic abstractions in place for things like create, when I did the python3 one, I believe I did some abstraction work around config handling there. It mostly depends on what you feel is needed for it to feel normal to the particular language you’re writing the binding for.

1 Like

Thanks for the reply!

Okay I need to figure that out in OCaml side as well actually…hm…

I find the abstraction level of go-lxc appropriate (I like the TemplateOptions), so I was mainly trying to get confirmation that the abstraction was sound etc.

One more question: Testing wise, I presume replicating lxc_test.go will be largely sufficient? Or would there be other heavier test suite I should reference to as well?

Something like lxc_test.go should be plenty. I believe our Go binding actually has a lot more tests than many of the other bindings mostly due to our concerns about threading/goroutines which was a bit of a new problem and lead to a lot of fixes in liblxc.

For newer bindings, I suspect testing your abstractions and any complex type conversion you may end up with is going to be the most useful. After that, if you can load configuration, modify it and start a container, you’re probably good.

1 Like

I’m going through go-lxc source code atm and got some more questions if you don’t mind answering.

Is there a reason why finalizers are not used for Container, and instead require use of Release?

I presume this is to do with concurrency+GC stuff? Or offering more precise semantics to users?

Many thanks!

EDIT: After some more digging, I was reminded fiinalizers are not guaranteed to run before program exits, which I presume would be a major reason for design route of explicit Release.

EDIT2: Right I I’m gonna say it’s just more difficult to deal with finalizers reliably after going through more golang articles, and having explicit Release is just easier to use and analyse.