0

We are trying to embed Python as a scripting language into our game engine that is built using C++. The summary of the issue is as follows:

Calling a C++ function that returns a pointer, in python results in a null object. We want to directly call/modify functions/variables from this pointer.

Gameobject is a C++ class that is passed when the Python Start() behavior is called. However, calling any methods (that returns a pointer) on this gameobject results in a null reference.

How do we bind the C++ function to the python module such that it returns a valid pointer (which is shared by C++ and python)?

We have tried various return policy types while binding, none of which seem to work. Eg: return_value_policy::reference, return_value_policy::reference_internal

C++ function definition
MusicComponent* GetMusicComponent() 
{
    assert(HasComponent<MusicComponent>() && "Does not have component.");
    auto ptr(componentArray[GetComponentTypeID<MusicComponent>()]);
    return dynamic_cast<MusicComponent*>(ptr);
}
Python binding implementation
//Unique pointer because the destructor and constructor are private 
py::class_<Gameobject , std::unique_ptr<Gameobject, py::nodelete>>gameobject (IridiumModule, "GameObject");


gameobject.def("GetMusicComponent", &Gameobject::GetMusicComponent, py::return_value_policy::automatic_reference);
Python Script
class PyScriptComponent():
    def Start(gameObject):       
       comp = gameObject.GetMusicComponent()
       print(comp) #prints none
       comp.PlayMusic() #error: null reference
Exposing MusicComponent
PYBIND11_MODULE(IridiumPython, IridiumModule) 
{
    py::class_<MusicComponent>musicComponent (IridiumModule, "MusicComponent" , baseComponent);
    baseComponent.def(py::init<Gameobject*>());
    musicComponent.def("PlayMusic", &MusicComponent::PlayMusic);
}

Calling the python function in the engine
pyObject.attr("Start")(GetGameobject());
iansmathew
  • 367
  • 1
  • 3
  • 13

1 Answers1

0

Another way of thinking about this problem, might be to use PYBIND11_EMBEDDED_MODULE, instead of having a pointer which is shared across Python and C++.

https://pybind11.readthedocs.io/en/stable/advanced/embedding.html#adding-embedded-modules

This way, the class will be "embedded" into the built in python modules you could have a class which is shared by Python and C++ and thus can be modified by either.

I would have expected return_value_policy::reference to work for you in this instance, however. It is possible that because it is being wrapped in a std::unique_ptr, that the resource is being cleaned up by C++ before it is used in Python and that is why you are getting a null reference.

Perhaps GetMusicComponent should return a unique_ptr rather than a raw pointer?

HarryP2023
  • 298
  • 1
  • 13