我们正尝试将Python作为脚本语言嵌入到使用C++构建的游戏引擎中。该问题摘要如下:
在 python 中调用返回指针的 C++ 函数会导致空对象。我们想从这个指针直接调用/修改函数/变量。
游戏对象是在调用 Python Start()
行为时传递的C++类。但是,在此游戏对象上调用任何方法(返回指针(都会导致空引用。
我们如何将 C++ 函数绑定到 python 模块,以便它返回一个有效的指针(由 C++ 和 python 共享(?
我们在绑定时尝试了各种退货政策类型,但似乎都不起作用。例如: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 绑定实现 //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);
蟒蛇脚本 class PyScriptComponent():
def Start(gameObject):
comp = gameObject.GetMusicComponent()
print(comp) #prints none
comp.PlayMusic() #error: null reference
公开音乐组件 PYBIND11_MODULE(IridiumPython, IridiumModule)
{
py::class_<MusicComponent>musicComponent (IridiumModule, "MusicComponent" , baseComponent);
baseComponent.def(py::init<Gameobject*>());
musicComponent.def("PlayMusic", &MusicComponent::PlayMusic);
}
在引擎中调用 python 函数 pyObject.attr("Start")(GetGameobject());
思考这个问题的另一种方式可能是使用 PYBIND11_EMBEDDED_MODULE
,而不是在 Python 和 C++ 之间共享指针。
https://pybind11.readthedocs.io/en/stable/advanced/embedding.html#adding-embedded-modules
这样,该类将被"嵌入"到内置的python模块中,您可以拥有一个由Python和C++共享的类,因此可以由其中任何一个进行修改。
但是,在这种情况下,我希望return_value_policy::reference
为您工作。有可能因为它被包装在一个std::unique_ptr
中,资源在C++在 Python 中使用之前被清理,这就是你得到一个空引用的原因。
也许GetMusicComponent应该返回一个unique_ptr而不是一个原始指针?