将Python对象转换为原生C++指针
我在考虑把Python当作嵌入式脚本语言来用在我正在做的项目上,基本上大部分功能都已经实现了。不过,我现在遇到一个问题,就是无法把一个Python扩展对象转换回原生的C++指针。
这是我的类:
class CGEGameModeBase
{
public:
virtual void FunctionCall()=0;
virtual const char* StringReturn()=0;
};
class CGEPYGameMode : public CGEGameModeBase, public boost::python::wrapper<CGEPYGameMode>
{
public:
virtual void FunctionCall()
{
if (override f = this->get_override("FunctionCall"))
f();
}
virtual const char* StringReturn()
{
if (override f = this->get_override("StringReturn"))
return f();
return "FAILED TO CALL";
}
};
Boost封装:
BOOST_PYTHON_MODULE(GEGameMode)
{
class_<CGEGameModeBase, boost::noncopyable>("CGEGameModeBase", no_init);
class_<CGEPYGameMode, bases<CGEGameModeBase> >("CGEPYGameMode", no_init)
.def("FunctionCall", &CGEPYGameMode::FunctionCall)
.def("StringReturn", &CGEPYGameMode::StringReturn);
}
还有Python代码:
import GEGameMode
def Ident():
return "Alpha"
def NewGamePlay():
return "NewAlpha"
def NewAlpha():
import GEGameMode
import GEUtil
class Alpha(GEGameMode.CGEPYGameMode):
def __init__(self):
print "Made new Alpha!"
def FunctionCall(self):
GEUtil.Msg("This is function test Alpha!")
def StringReturn(self):
return "This is return test Alpha!"
return Alpha()
现在我可以通过以下方式正常调用前两个函数:
const char* ident = extract< const char* >( GetLocalDict()["Ident"]() );
const char* newgameplay = extract< const char* >( GetLocalDict()["NewGamePlay"]() );
printf("Loading Script: %s\n", ident);
CGEPYGameMode* m_pGameMode = extract< CGEPYGameMode* >( GetLocalDict()[newgameplay]() );
但是当我尝试把Alpha类转换回它的基类(上面最后一行)时,我遇到了一个Boost错误:
TypeError: No registered converter was able to extract a C++ pointer to type class CGEPYGameMode from this Python object of type Alpha
我在网上搜索了很多,但还是搞不清楚怎么把Alpha对象转换成它的基类指针。我可以把它当作对象使用,但我更希望它能作为指针,这样一些不支持Python的代码也能使用。有没有什么建议?
3 个回答
0
我不确定这是否对你有帮助,但我之前在Lua脚本中遇到过同样的问题。我们在Lua中创建了对象,然后想用一些C++代码通过指针来处理这些对象。我们做了以下几件事:
- 所有与对象相关的内容都是用C++写的,包括构造函数、析构函数和工厂方法;
- Lua代码调用一个工厂方法来创建对象。这个工厂方法做了两件事:1) 给对象分配一个唯一的ID号码,2) 在C++的一个映射表中注册这个ID和对应的指针;
- 所以,每当Lua要把一个指针传给C++代码时,它实际上是传递了一个对象的ID,然后C++代码通过这个ID在映射表中查找实际的指针。
1
这可能不是你想要的答案,但可以看看ChaiScript,它可以嵌入到你的C++应用程序中。
根据他们的网站,
ChaiScript是第一个也是唯一一个从一开始就考虑到与C++兼容的脚本语言。它是一种受ECMAScript启发的、嵌入式的类似函数的语言。
ChaiScript没有元编译器,没有库依赖,没有构建系统的要求,也没有任何遗留的负担。它可以与任何你暴露给它的C++函数无缝工作。你不需要明确告诉它任何类型,它是以函数为中心的。
使用ChaiScript,你实际上只需在你的程序中添加三行代码,就可以开始编写脚本,而完全不需要修改你的构建步骤。
2
感谢Stefan在Python和C++的邮件列表中提供的帮助,我之前漏掉了
super(Alpha, self).__init__()
在构造函数调用中,这导致父类没有被创建。我原以为这个过程会自动完成 :D
我遇到的另一个问题是,如果不把新创建的类实例保存为全局变量,它会在超出作用域后被清理掉。
现在我很开心!