When I had first started approaching the task of making C++ bindings around a go library, I hit some walls and asked about it on StackOverflow
. I got no replies, and ended up getting a working solution. However, I wanted to check this approach with the community to see if I could have done this a better way.
has 2 structs and a few functions that I wanted to make available as a C++ library. Since the cgo rules disallowed C++ storing pointers for undetermined periods of time, and also passing memory containing pointers at all, I had to figure out how to make objects that contain state accessible to C++.
What I ended up doing was to create a private package level map, where I associate instances of the objects with a unique uint64 id, and then give that to C++ as an opaque handle:
I also use a reference counting approach, so that C++ can copy and destruct and ultimately trigger the removal of these objects, by id:
Then all of the wrapper methods in C++ simply delegate to Go exported functions, using the id:
This all works. However, there is a mutex guarded map now, around all object access. It uses a write lock for object create/delete, and a read lock for method access.
Some random performance tests show, when creating 100k FileSequence instances and calling 4 different getters, I get:
Python (original library): 8.0s
Go (port from python): 1.9s
C++ bindings over Go: 3.2s
So all that being said, is there a way I could have approached this binding without a global map? It seems really straightforward to export plain data to C/C++ but when it comes to exposing functionality for objects that have state and methods, I couldn't come up with anything better.
Much appreciated for any insight! It was a really interesting learning experience so far.