I’ve been trying some things with python callback functions in C++ classes. Here’s what I’m trying to do:
(1) I have two C++ classes, MyClass and MySecondClass, both useable from python (using interrogate)
(2) the users sets the callback using MyClass.set_callback(PyObject myPythonFunc)
(3) whenever my class feels like it, it calls the callback function using PyEval_CallObject
(4) when calling the callback function, it passes a MySecondClass instance as parameter to the function.
With 1-3 I have no trouble, just with 4. I know I need to pass a PyObject, but I can’t seem to find a way to get a Panda class and grab it as PyObject (I know its related to Dtool_PyInstDef but that doesn’t bring me much further).
I’ve been looking around in py_panda.h but am still clueless how to do this. Or isn’t there a clean solution for this at all?
Thanks for your reply! This seems to work good, I had to change Dtool_TypedReferenceCount to Dtool_MySecondClass, (otherwise I’d get a TypedReferenceCount object in python and not what I want), and had to add these lines to the top of my file:
If you just got a plain TypedReferenceCount pointer in Python, it might mean that you haven’t interfaced with Panda’s runtime typing system properly. Coincidentally, I’ve been noticing this error message at startup lately:
:interrogatedb(warning): Class GeoMipTerrain has a zero TypeHandle value; check that init_type() is called.
Yeah, I just noticed I forgot the init_type just a few seconds before I read your post. Just fixed it in the config_grutil file.
I didn’t actually notice it because I had notify-level-interrogatedb to “error”, because of a different warning that annoyed me.
So, I guess it’s illegal to do it my way, even though it seems to work?
It’s perfectly legal to do it with an explicit cast to the known type. No reason to change that.
It’s just that, if you had the TypeHandle initialized properly, it should have also worked with a cast to TypedReferenceCount, because from there the dynamic runtime type system would have automatically downcast it to the appropriate type.
We have to shadow all of the Python calls we make in dtool/src/pystub/pystub.cxx. Take a look at this file and add the new Python call to it (it goes in two different places). Should be pretty clear where it belongs; the list is in alphabetical order.
I just realized that DTool_CreatePyInstanceTyped() will “steal” a reference to the ReferenceCount object you pass in, at least if you pass true for the third parameter (which you should), so it’s necessary to explicitly up the reference count of your object first: