It all appears to be due to a lack of semantics in the C header. SWIG depends on specifying this stuff in the interface file, but I've often wondered if it wouldn't be better to enhance the C-side, either by standard parameter name conventions or by some Doxygen-like standard comments to indicate ownership and other stuff.
SWIG has this nice potential to generate wrappers for (m)any language(s), but in practice as you said it's often just easier to use the Python API directly instead of trying to make it too general. Shame.
I'm really glad that you acknowledged this — I work with a lot of non-ASCII text and have run into that more than a few times in real code.
For example, the binding of an accelerated HyperLogLog implementation only requires tiny amount of work, plus a line in my Makefile:
PYBIND11_MODULE(_hll, m) {
m.doc() = "pybind11-powered HyperLogLog"; // optional module docstring
py::class_<hll_t> (m, "hll")
.def(py::init<size_t>())
.def("clear", &hll_t::clear, "Clear all entries.")
.def("resize", &hll_t::resize, "Change old size to a new size.")
.def("sum", &hll_t::sum, "Add up results.")
.def("report", &hll_t::report, "Emit estimated cardinality. Performs sum if not performed, but sum must be recalculated if further entries are added.")
.def("add", &hll_t::add, "Add a (hashed) value to the sketch.")
.def("addh_", &hll_t::addh, "Hash an integer value and then add that to the sketch.");
}
[1] https://github.com/pybind/pybind11[1] http://pybind11.readthedocs.io/en/master/basics.html#creatin...
It's not as simple as milksnake. I would like to see some smarter extensions added to pybind11, but I'm okay with that for now.
I would love to see people showing how to do simple string processing, like counting characters in proper grapheme cluster level in their favorite programming language.
for (c1, c2) in val.chars().zip(val.chars().skip(1))
chars() iterates by unicode scalar values. It'd be bytes() for bytes.If you wanted to do it by grapheme clusters, you'd add https://crates.io/crates/unicode-segmentation to your Cargo.toml, add the relevant imports you see on that page to your code, and change the above line to
for (c1, c2) in UnicodeSegmentation::graphemes(val, true).zip(UnicodeSegmentation::graphemes(val, true).skip(1))
... possibly splitting that up into variables becuase dang, that's a long line.Then, you're getting &strs instead of chars for the iteration, but I think the body still says the same, as == checks by value.
Works well this way with Rust too.
https://github.com/martinxyz/rust-python-example/commit/f8e3...