Haiku-PyAPI: Python bindings for the Haiku API

Thank you @Zardshard . This project will not exist if it wasn’t for @coolcoder613 and You.

Uh! didn’t notice that! There was a crash when config file was not set up. Next update will fix this! thank you for notifying me this bug. The update is already published in haikuports, waiting for approval.

BTW FeedGator received an update fixing a major bug happening when there are a lot of files in a single folder. So next update is strongly suggested. This also is waiting for approval.


Next step: provide documentation for Storage Kit, fix some functions (some already spotted and fixed), provide pythonic versions of the API where needed.

Stay tuned :wink:

Edit:

There’s also an updated app from @coolcoder613 : Bemini: a Gemini client for Haiku (Gemini the protoco not the AI)

4 Likes

What happens with status = message.FindString("key", outputString)? outputString is an undefined name on the right hand side of the assignment expression?

Wouldn’t this be the natural way?

try:
        outputString = message.FindString("key")
except KeyError:
        ...

You have to do something more like

outputString = ""
status = message.FindString("key", outputString)

otherwise Python will indeed complain about outputString being undefined.

Yes, that seems even more Pythonic than what we have. I think there are plenty of similar changes that we can make if we’re willing to only loosely mirror Haiku’s API.

But then we would have a lot more design decisions to make for the API as well as more to document. So we’ve thus far stuck to only low-hanging fruit.

FYI, what I do for foreign function interfaces, is a variation on the include file. Starting with app/Message.h, I annotate the functions for various issues that are unfortunately not documented in a genuine C++ include file, like whether a parameter is input or output. And I have to rename some functions, because nothing supports C++ function overloading. Hence,

status_t  FindString(const char * name-p, const char *& string-v);
status_t  FindString_i(const char * name-p, int32  index-p, const char *& string-v);

Have to parse that, and implement consistent rules for what a C++ function naturally translates to, in the host language. (-p stands for parameter, -v for (return) value. We also have names, if the language supports named parameters, and you can put in default values here.) This general approach is really necessary when you’re supporting this many different functions, so you can make changes to the implementation logic without having to recode all those functions.

I can’t think of any case where a status_t wouldn’t be treated as an exception if not B_OK, or any other function type that would - it’s very possible I’m forgetting one or two, but there sure isn’t much of this. Function signatures have been mostly pretty cut and dried - rarely multiple return values, read/write parameters etc. One thing I think you particularly have to watch out for with Python, is ownership, like the BMessage that we pass to BControl subclasses if I remember right, you have to increment the reference count there, and the C++ include file of course gives you no hint about this.

Ironically, even though Python technically doesn’t support function overloading, pybind11 still implements it. In other words, we haven’t needed to worry about this at all!

Yes, that’s one of the things that still needs to be done. The amount of py::nodeletes, which tells Python never to delete an object, is atrocious! Needless to say we have a lot of memory leaks that still need to be fixed. :sweat_smile:

and this could not be done as python strings are immutable in the binding,
this is the reason for using this wrapper:

py::tuple PythonicFindStringWrapper(const BMessage& self, const char* name, int32 n=0){
	const char* s;
	status_t status = self.FindString(name, n, &s);
	if (status == B_OK) {
        std::string safe_string(s);
        return py::make_tuple(status, safe_string);
    }
    return py::make_tuple(status, std::string("")); 
}

so as it is now, in python we do:

status, outstring=message.FindString("key")

oh yes! That’s a lot more pythonic using try/except! But AFAIK, using try/except blocks in Python can introduce some performance overhead, especially if exceptions are raised frequently. But if it’s more appropriate to use try/except we can consider using that

edited: accidentally posted the wrong source code ^^’

3 Likes