python – Swig从Base *向下转换为Derived *
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python – Swig从Base *向下转换为Derived *,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含3078字,纯文字阅读大概需要5分钟。
内容图文
![python – Swig从Base *向下转换为Derived *](/upload/InfoBanner/zyjiaocheng/697/098b48b62f8f44e4855feaeb1d31c523.jpg)
我有以下c类(简化),我使用SWIG向Python公开:
struct Component
{
virtual void update();
}
struct DerivedComponent : public Component
{
void update() { cout << "DerivedComponent::update()" << endl; }
void speak() { cout << "DerivedComponent::speak()" << endl; }
}
class Entity
{
public:
Component* component(const std::string& class_name)
{
return m_components[class_name];
}
private:
std::unordered_map<std::string, Component*> m_components;
}
现在,在Python中,我可以在Entity实例上成功调用component(“DerivedComponent”).update().但是,我不能调用component(“DerivedComponent”).speak(),因为组件返回的类型(“DerivedComponent”)被报告为< class'module.Component'>.
我显然需要向下转换component()函数的结果,以便调用DerivedComponent中定义的方法.我曾希望Swig会像我相信Boost.Python那样执行自动向下转换.
如果没有在c中定义一大堆类型转换函数并将它们暴露给Python,那么使用Swig或Python进行向下转换是否有更好的解决方案?我有什么选择?
解决方法:
您可以通过一些工作在Python中完成您想要的任务.它可以正常工作,因为在Python中,向下转换是没有意义的,因为函数的返回类型(或一般类型)不是强类型的,所以我们可以修改你的Entity :: component函数,以便始终返回最派生的类型,无论如何这是什么.
要使用C / Python绑定工作,您需要为Entity :: component编写一个’out’类型映射.我写了一个如何工作的例子.在这种情况下,我们必须略微提出它,因为知道向下传播它的唯一方法来自函数的参数. (例如,如果您的基类有一个方法,将其作为字符串/枚举返回,您可以进一步简化此操作而不依赖于输入参数).
%module test
%{
#include "test.hh"
%}
%include <std_string.i>
%typemap(out) Component * Entity::component {
const std::string lookup_typename = *arg2 + " *";
swig_type_info * const outtype = SWIG_TypeQuery(lookup_typename.c_str());
$result = SWIG_NewPointerObj(SWIG_as_voidptr($1), outtype, $owner);
}
%include "test.hh"
这使用SWIG_TypeQuery函数要求Python运行时基于arg2查找类型(对于您的示例,这是字符串).
我必须对你的示例标题(在我的示例中命名为test.hh)进行一些更改以修复一些问题,然后才能将其转换为完全正常运行的演示,它最终看起来像:
#include <iostream>
#include <map>
#include <string>
struct Component
{
virtual void update() = 0;
virtual ~Component() {}
};
struct DerivedComponent : public Component
{
void update() { std::cout << "DerivedComponent::update()" << std::endl; }
void speak() { std::cout << "DerivedComponent::speak()" << std::endl; }
};
class Entity
{
public:
Entity() {
m_components["DerivedComponent"] = new DerivedComponent;
}
Component* component(const std::string& class_name)
{
return m_components[class_name];
}
private:
std::map<std::string, Component*> m_components;
};
然后我用它构建它:
swig -py3 -c++ -python -Wall test.i
g++ -Wall -Wextra test_wrap.cxx -I/usr/include/python3.4/ -lpython3.4m -shared -o _test.so
有了这个,我就可以运行以下Python:
from test import *
e=Entity()
print(e)
c=e.component("DerivedComponent")
print(c)
print(type(c))
c.update()
c.speak()
这有效,你希望:
<test.Entity; proxy of <Swig Object of type 'Entity *' at 0xb7230458> >
Name is: DerivedComponent *, type is: 0xb77661d8
<test.DerivedComponent; proxy of <Swig Object of type 'DerivedComponent *' at 0xb72575d8> >
<class 'test.DerivedComponent'>
DerivedComponent::update()
DerivedComponent::speak()
内容总结
以上是互联网集市为您收集整理的python – Swig从Base *向下转换为Derived *全部内容,希望文章能够帮你解决python – Swig从Base *向下转换为Derived *所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。