【发布时间】:2014-08-29 15:53:02
【问题描述】:
我有一个 C++ 库,其中定义了 2 个类:t_foo_base 和 t_foo。 t_foo 派生自 t_foo_base。它们都实现了一个虚函数text。此函数返回一个带有当前类名称的字符串。我使用 boost.python 为这个库和这个类生成一个包装器。
我在 python 脚本中导入这个库。在这个脚本中,我实现了一个函数。该函数接受一个参数并在其上调用函数“text()”。
现在我将这个 python 脚本导入到 C++ 应用程序中。我再次使用 boost.python。我从 python 脚本中得到函数“test_function”并这样调用它:
t_foo_base foo_base;
test_function( foo_base );
t_foo foo;
test_function( foo );
t_foo_base* foo_base_tpr = new t_foo_base;
test_function( *foo_base_tpr );
t_foo_base* foo_ptr = new t_foo;
test_function( *foo_ptr );
输出是:
t_foo_base
t_foo
t_foo_base
t_foo_base
我会将输出的第 4 行解释为“t_foo”,而不是“t_foo_base”。
看起来,通过基类指针传递派生对象会“删除”派生对象的所有特性。有没有办法解决这个问题?
我正在使用 Visual Studio 2013、Python 3.4 和 Boost 1.56.0。
这是来自 C++ 库的代码:
-- 文件 t_foo.h--
class __declspec( dllexport ) t_foo_base
{
public:
t_foo_base(){};
virtual ~t_foo_base(){}
virtual std::string text( void ) const { return( "t_foo_base" ); };
};
class __declspec( dllexport ) t_foo: public t_foo_base
{
public:
t_foo(){};
virtual std::string text( void ) const override { return( "t_foo" ); };
};
-- 文件 t_foo.cpp--
#include "t_foo.h"
#include <boost/python.hpp>
using namespace boost::python;
BOOST_PYTHON_MODULE( ex_three_lib )
{
class_< t_foo_base >( "t_foo_base" )
.def( "text", &t_foo_base::text );
class_< t_foo, bases< t_foo_base > >( "t_simple_callback" )
.def( "text", &t_foo::text );
}
这是python脚本:
import ex_three_lib
def test_function( item ):
print( item.text() )
print( "no function call here" )
这是 C++ 应用程序:
void
init_module_ex_three_lib
(
void
);
boost::python::object
import_python_object( const std::string& p_name, const std::string& p_path, boost::python::api::object& p_global )
{
using namespace boost::python;
try
{
dict locals;
locals[ "modulename" ] = p_name;
locals[ "path" ] = p_path;
exec
(
"import imp\n"
"newmodule = imp.load_module( modulename, open( path ), path,( 'py', 'U', imp.PY_SOURCE ) )\n",
p_global,
locals
);
return locals[ "newmodule" ];
}
catch( boost::python::error_already_set const & )
{
if( PyErr_ExceptionMatches( PyExc_ZeroDivisionError ) )
{
assert( false );
}
else
{
PyErr_Print();
}
}
}
int
main
(
void
)
{
Py_Initialize();
init_module_ex_three_lib();
try
{
boost::python::object main_module = boost::python::import( "__main__" );
boost::python::object main_namespace = main_module.attr( "__dict__" );
{
boost::python::object script = import_python_object
(
"ex_one_script",
"ex_three_script.py",
main_namespace
);
boost::python::object test_function = script.attr( "test_function" );
t_foo_base foo_base;
test_function( foo_base );
t_foo foo;
test_function( foo );
t_foo_base* foo_base_tpr = new t_foo_base;
test_function( *foo_base_tpr );
t_foo_base* foo_ptr = new t_foo;
test_function( *foo_ptr );
}
}
catch( boost::python::error_already_set const & )
{
if( PyErr_ExceptionMatches( PyExc_ZeroDivisionError ) )
{
assert( false );
}
else
{
PyErr_Print();
}
}
}
【问题讨论】:
-
好吧,如果
test_function按值获取test_foo对象,则此调用将无法正常工作:test_function( *foo_ptr );多态性仅在传递指针或引用而不是值时才有效。由于我不知道 boost::python,也许你可以确认一下? -
看看这个简单的 C++ 程序,向您展示我所指的内容:ideone.com/M326Pz 请注意,即使程序从基指针创建派生对象,被调用的函数也会获取一个值,不是指针或引用。所以你需要检查这是否是你正在尝试做的事情。
标签: python c++ python-3.x boost boost-python