Boost Python 和 OGRE - 具有相同代码的不同结果
Posted
技术标签:
【中文标题】Boost Python 和 OGRE - 具有相同代码的不同结果【英文标题】:Boost Python and OGRE - Different results with equivalent code 【发布时间】:2014-09-07 16:29:18 【问题描述】:我会重新发布what I posted on the OGRE forums:
我不确定是在这里发帖还是在“在实践中使用 OGRE”论坛发帖更好,但我会试一试,因为这是看板中最常出现的部分。
所以我正在为我自己的在内部使用 OGRE 的框架进行绑定,我已经绑定了核心对象,并且在大多数情况下它们工作正常(输入和窗口工作正常),但我遇到了这个问题我无法深入了解 - Python 应用程序的视口始终为黑色(除了相机,我没有其他对象,只是设置视口的背景颜色)。
奇怪的是 - C++ 中的完全等价物可以正常工作,但 python 绑定的代码却不能。日志中没有显示任何重要的内容。
这是我绑定对象的方法:
#include "boost/python.hpp"
#include "boost/exception/diagnostic_information.hpp"
#include "Demo.hpp"
#include "Demo.cpp"
#include "XMLLevelLoader.h"
void addResourceLocation(const Crimson::String& group, const Crimson::String& loc)
Ogre::ResourceGroupManager* resmgr = Ogre::ResourceGroupManager::getSingletonPtr();
resmgr->addResourceLocation(loc, "FileSystem", group);
void initResourceGroup(const Crimson::String& group)
Ogre::ResourceGroupManager* resmgr = Ogre::ResourceGroupManager::getSingletonPtr();
resmgr->initialiseResourceGroup(group);
class AppWrapper : public Crimson::Application, public boost::python::wrapper<Crimson::Application>
public:
void onKeyDown(const SDL_KeyboardEvent& e)
boost::python::override over = this->get_override("onKeyDown");
if (over)
over(e);
using Crimson::Application::mQuit;
;
BOOST_PYTHON_MODULE(PyEngine)
using namespace boost::python;
def("initResourceGroup", initResourceGroup);
def("addResourceLocation", addResourceLocation);
enum_<SDL_Scancode>("SDL_Scancode");
class_<Ogre::ColourValue>("Color", init<const float, const float, const float, const float>())
.def_readwrite("r", &Ogre::ColourValue::r)
.def_readwrite("g", &Ogre::ColourValue::g)
.def_readwrite("b", &Ogre::ColourValue::b)
.def_readwrite("a", &Ogre::ColourValue::a);
class_<Ogre::Viewport>("Viewport", init<Ogre::Camera* , Ogre::RenderTarget*, float, float, float, float, int>())
.def("setBackgroundColour", &Ogre::Viewport::setBackgroundColour);
class_<Crimson::WindowInfo>("WindowInfo")
.def_readonly("renderWnd", &Crimson::WindowInfo::renderWnd)
.def_readonly("sdlWnd", &Crimson::WindowInfo::sdlWnd)
.def("addViewport", &Crimson::WindowInfo::addViewport, return_value_policy<reference_existing_object>())
.def("getAspectRatio", &Crimson::WindowInfo::getAspectRatio)
.def("getWidth", &Crimson::WindowInfo::getWidth)
.def("getHeight", &Crimson::WindowInfo::getHeight);
class_<Crimson::Kernel>("Kernel")
.def("initialize", &Crimson::Kernel::initialize)
.def("createRenderWindow", &Crimson::Kernel::createRenderWindow, return_value_policy<reference_existing_object>())
.def("getWindowInfo", &Crimson::Kernel::getWindowInfo, return_value_policy<reference_existing_object>())
.def("destroy", &Crimson::Kernel::destroy)
.def("render", &Crimson::Kernel::render);
class_<Crimson::Actor>("Actor", init<Crimson::Level*, const Crimson::String&, Crimson::Actor*>())
.def("setPosition", static_cast<void(Crimson::Actor::*)(const Crimson::Vector3&)>(&Crimson::Actor::setPosition))
.def("getPosition", &Crimson::Actor::getPosition);
class_ <Crimson::Mesh, bases<Crimson::Actor>>("Mesh", init<Crimson::Level*, const Crimson::String&, const Crimson::String&, Crimson::Actor*>());
class_ <Crimson::Camera, bases<Crimson::Actor>>("Camera", init<Crimson::Level*, const Crimson::String&, Crimson::Actor*>())
.def("setAspectRatio", &Crimson::Camera::setAspectRatio);
class_<rapidxml::xml_node<>, boost::noncopyable>("xml_node", init<rapidxml::node_type>())
.def("first_node", &rapidxml::xml_node<>::first_node, return_value_policy<reference_existing_object>());
class_<rapidxml::xml_document<>, boost::noncopyable>("xml_document")
.def("first_node", &rapidxml::xml_document<>::first_node, return_value_policy<reference_existing_object>())
.def("parse", &rapidxml::xml_document<>::parse<0>);
class_<Crimson::Level>("Level", init<Crimson::Kernel*>())
.def("initialize", &Crimson::Level::initialize)
.def("destroy", &Crimson::Level::destroy)
.def("createActor", &Crimson::Level::createActor, return_value_policy<reference_existing_object>())
.def("createMesh", &Crimson::Level::createMesh, return_value_policy<reference_existing_object>())
.def("createCamera", &Crimson::Level::createCamera, return_value_policy<reference_existing_object>());
class_<Crimson::XMLLevelLoader>("XMLLevelLoader", init<Crimson::String>())
.def("load", &Crimson::XMLLevelLoader::load)
.def("loadFileAsString", &Crimson::XMLLevelLoader::loadFileAsString)
.def("loadResources", &Crimson::XMLLevelLoader::loadResources)
.staticmethod("loadFileAsString")
.staticmethod("loadResources");
class_<AppWrapper, boost::noncopyable>("Application")
.def("initialize", &Crimson::Application::initialize)
.def("destroy", &Crimson::Application::destroy)
.def("onKeyDown", &Crimson::Application::onKeyDown)
.def("start", &Crimson::Application::start)
.def("updateGraphics", &Crimson::Application::updateGraphics)
.def("updateInput", &Crimson::Application::updateInput)
.def("isRunning", &Crimson::Application::isRunning)
.def("quit", &Crimson::Application::quit)
.def("getKernel", &Crimson::Application::getKernel, return_value_policy<reference_existing_object>());
class_<SDL_Keysym>("SDL_Keysym")
.def_readonly("mod", &SDL_Keysym::mod)
.def_readonly("scancode", &SDL_Keysym::scancode);
class_<SDL_KeyboardEvent>("SDL_KeyboardEvent")
.def_readonly("keysym", &SDL_KeyboardEvent::keysym);
class_<Ogre::Vector3>("Vector3", init<const float, const float, const float>())
.def_readwrite("x", &Ogre::Vector3::x)
.def_readwrite("y", &Ogre::Vector3::y)
.def_readwrite("z", &Ogre::Vector3::z);
Python 代码(空白视口):
import sys
from PyEngine import *
# Class definition
class TestPythonApp(Application):
def initialize(self):
Application.initialize(self)
mLevel = Level(self.getKernel())
mLevel.initialize()
mCamera = mLevel.createCamera("test", None)
vp = self.getKernel().getWindowInfo().addViewport(mCamera)
vp.setBackgroundColour(Color(0.8, 0, 0, 1))
def start(self):
while self.isRunning():
self.updateInput()
self.updateGraphics(1)
mLevel = None
mCamera = None
# /Class definition
# Script execution
app = TestPythonApp()
app.initialize()
app.start()
app.destroy()
C++ 等效项(彩色视口):
-- 标题
#ifndef PYAPP_HPP
#define PYAPP_HPP
#include "Application.h"
#include "XMLLevelLoader.h"
class PythonApp : public Crimson::Application
public:
bool initialize();
void start();
protected:
Crimson::Camera* mCamera;
Crimson::Level* mLevel;
;
#endif
-- Source:
bool PythonApp::initialize()
Application::initialize();
mLevel = new Crimson::Level(mKernel);
mLevel->initialize();
mCamera = mLevel->createCamera("cam");
Ogre::Viewport* vp = mKernel->getWindowInfo()->addViewport(mCamera);
vp->setBackgroundColour(Ogre::ColourValue(0.7f, 0.8f, 0.7f));
return true;
void PythonApp::start()
while (isRunning())
updateInput();
updateGraphics(1);
int main(int argc, char* argv[])
PythonApp game;
game.initialize();
game.start();
game.destroy();
return 0;
我做了检查 - mBackColor
(在 Ogre::Viewport 中)已通过 Python 正确设置,所以这不是问题。
此外,如果我将渲染循环放在initialize()
函数内,Python 代码会因某种原因正常工作,但如果它不在此范围内,则不会。正因为如此,我觉得这是一个上下文问题(也许当解释器退出初始化函数或其他东西时数据被破坏了。
这是奇怪的 Python 代码:
import sys
from PyEngine import *
# Class definition
class TestPythonApp(Application):
def initialize(self):
Application.initialize(self)
mLevel = Level(self.getKernel())
mLevel.initialize()
mCamera = mLevel.createCamera("test", None)
vp = self.getKernel().getWindowInfo().addViewport(mCamera)
vp.setBackgroundColour(Color(0.8, 0, 0, 1))
self.start() # Moved line app.start() to here.
def start(self):
while self.isRunning():
self.updateInput()
self.updateGraphics(1)
mLevel = None
mCamera = None
# /Class definition
# Script execution
app = TestPythonApp()
app.initialize()
#app.start() # This moved up to initialize makes it work
app.destroy()
-- 关于我的框架的一些信息:内核包含和调用Ogre::Root
,mLevel
包含一个场景管理器,mCamera
是一个普通的 OGRE 相机,只是通过我自己的 API 包装以方便使用 WindowInfo 是另一个处理窗口设置(在 OGRE 和 SDL 之间)的包装类,我只是在我的 updateGraphics(delta)
函数中调用 renderOneFrame()
。
那么我做错了什么,与 C++ 调用具有相同调用的 python 代码导致不同的结果?
【问题讨论】:
【参考方案1】:好的,所以在设置了很多断点之后,我发现当解释器退出函数 initialize()
时,它破坏了 mLevel
和 mCamera
对象,因为(我是 Python 新手)我忘记了在 Python 中 self/this 不是隐含的,因此我的对象由于 Ogre::SceneManager
的破坏而被破坏(在删除 mLevel
时)。
更新(工作)代码:
import sys
from PyEngine import *
# Class definition
class TestPythonApp(Application):
def initialize(self):
Application.initialize(self)
self.mLevel = Level(self.getKernel())
self.mLevel.initialize()
self.mCamera = self.mLevel.createCamera("test", None)
self.mViewport = self.getKernel().getWindowInfo().addViewport(self.mCamera)
self.mViewport.setBackgroundColour(Color(0.8, 0, 0, 1))
print("Object: %s, of size: %d" % (self.mViewport, sys.getsizeof(self.mViewport)))
#self.start();
def start(self):
while self.isRunning():
self.updateInput()
self.updateGraphics(1)
mLevel = None
mViewport = None
mCamera = None
# /Class definition
# Script execution
app = TestPythonApp()
print("Initing");
app.initialize()
print("Object: %s, of size: %d" % (app.mViewport, sys.getsizeof(app.mViewport)))
app.start() # This moved up to initialize makes it work
app.destroy()
【讨论】:
那么,这个问题解决了吗?通过在Ogre3D forums 阅读您自己的答案,我认为是这样。如果是,请将您自己的答案标记为“已接受”。 是的,我想我当时由于某种原因无法接受自己的答案,现在完成了。以上是关于Boost Python 和 OGRE - 具有相同代码的不同结果的主要内容,如果未能解决你的问题,请参考以下文章