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
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());