watcher icon indicating copy to clipboard operation
watcher copied to clipboard

Lua, Ruby, Haskell, Go Language bindings and FFI support

Open e-dant opened this issue 1 year ago • 12 comments

There are some languages with ecosystems which could benefit from this filesystem watcher.

This is an efficient, reasonably well tested filesystem watcher with a small, relatively stable API.

There isn't much to expose or package.

I think this is mostly a matter of figuring out the "right way" to expose a library with a C ABI to these languages, and then just doing it.

e-dant avatar Jul 13 '24 02:07 e-dant

Python and Node.js are mostly done. I want to test them a bit more before uploading to pip and npm.

Haskell and Ruby were trickier.

  • Haskell doesn't compile C++ correctly. Their use of gcc seems to ignore a bunch of include paths and options needed to compile C++ correctly. A workaround might be a custom Setup.hs, but writing that in a way that's amenable to packaging isn't something I know how to do yet.

  • Ruby's Fiddle (ffi) module has some odd behavior when creating bindings for functions which take non-builtin types. For example, void* wtr_watcher_open(char const*, struct wtr_watcher_event) was problematic for Ruby. A workaround might be to write a Ruby extension (instead of just interfacing with a shared library over ffi).

e-dant avatar Jul 25 '24 11:07 e-dant

Would you consider Go bindings (using cgo)?

If it’s possible to call the library from pure C (exposing a C header file) this will be easy (and I can help with this).

dunglas avatar Sep 07 '24 14:09 dunglas

Would you consider Go bindings (using cgo)?

That sounds like a good idea to me

If it’s possible to call the library from pure C (exposing a C header file) this will be easy (and I can help with this).

I built one here: https://github.com/e-dant/watcher/blob/next/watcher-c/include/wtr/watcher-c.h

The C project builds as a static or shared library. It has some basic tests and examples (but of course the majority of our tests are elsewhere).

The C api may change, but not in dramatic ways. (You'll notice a second pipe-based api there, intended to make some language bindings easier. I'm thinking of removing it.)

e-dant avatar Sep 07 '24 22:09 e-dant

I can help with this

Thank you :)

e-dant avatar Sep 07 '24 22:09 e-dant

Would you prefer bindings to be in this repository (a Go module) or in a separate one? My preference would be to store it in this repo.

dunglas avatar Sep 08 '24 16:09 dunglas

Entirely up to you. This repo would work.

e-dant avatar Sep 08 '24 18:09 e-dant

If you choose to set it up in this repo, would you mind adding a little blurb for Go in the changelog for 0.12? Please do add an @dunglas to those parts of the changelog if you don't mind.

I'll cut a release soon. (Whenever Github resolves this InternalError: error creating tlog entry - (502) Bad Gateway issue when signing our workflow artifacts.)

e-dant avatar Sep 08 '24 18:09 e-dant

Would you consider passing the wtr_watcher_event by address to the wtr_watcher_callback, instead of by value? Specifically LuaJIT ffi does not support callback with pass by value argument.

Fyi, libuv had this discussion too.

gnois avatar Nov 01 '24 03:11 gnois

Would you consider passing the wtr_watcher_event by address to the wtr_watcher_callback, instead of by value? Specifically LuaJIT ffi does not support callback with pass by value argument.

Fyi, libuv had this discussion too.

Yes, I think that's worth exploring.

While the project is still major version 0, I do try not to break things... but portability is important.


Maybe another function, which passes events by reference, is appropriate here?

Maybe another function which, instead of being callback-based, is pipe-based, is also appropriate? (Would that make things even easier?)

e-dant avatar Nov 01 '24 04:11 e-dant

Not sure how a pipe-based API would look like... But I'd be content with the current callback based API with pass by addr argument, which would already make LuaJIT ffi easy. :)

gnois avatar Nov 01 '24 09:11 gnois

I'd be content with the current callback based API with pass by addr argument, which would already make LuaJIT ffi easy. :)

WIP on https://github.com/e-dant/watcher/commit/1f0853d53d00ec3b1723b49ec44edcbac0d547c8

I want to add some documentation and roll over some bikeshedding stuff before cutting a release.

Re bikeshedding:

  • It is a bit redundant to have both wtr_watcher_open and ..._eventref_stream.
  • The name is long, and weird.
  • ... But, just changing the current api makes me worry. I'm hesitant to break compatibility without a compelling reason.

e-dant avatar Nov 02 '24 00:11 e-dant

My 2 cents: prefer breaking the API while it's still in 0.x than inherit a badly named or designed API for the whole life of the project 😅

dunglas avatar Nov 02 '24 06:11 dunglas