我有一个C ++库,其中定义了2个类: t_foo_base 和 t_foo 。 t_foo派生自t_foo_base。它们都实现了虚拟功能文本。此函数返回一个包含当前类名称的字符串。我使用boost.python为这个库和这个类生成一个包装器。
我在python脚本中导入这个库。在这个脚本中我实现了一个函数。该函数接受一个参数并调用函数" text()"在它上面。
现在我在C ++应用程序中导入这个python脚本。我再次使用boost.python。我得到了函数" test_function"从python脚本中调用它:
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 );
outpur是:
t_foo_base
t_foo
t_foo_base
t_foo_base
我会将输出的第4行显示为" t_foo",而不是" t_foo_base"。
看来,通过其基类指针传递派生对象"切掉了#34;派生对象的所有功能。有没有办法解决这个问题?
我正在使用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();
}
}
}
答案 0 :(得分:1)
您应该在这里使用boost::ref(...)
。这基本上会将任何值/指针转换为它的引用。另请参阅Calling Python Functions and Methods
t_foo_base foo_base;
test_function( boost::ref(foo_base) );
t_foo foo;
test_function( boost::ref(foo) );
t_foo_base* foo_base_tpr = new t_foo_base;
test_function( boost::ref(*foo_base_tpr) );
t_foo_base* foo_ptr = new t_foo;
test_function( boost::ref(*foo_ptr) );
- &GT;
t_foo_base
t_foo
t_foo_base
t_foo