我有一个带有 C++ python 扩展的库(C++ 调用 python,而后者又调用 C++)使用 boost::python 和 python 库(这很混乱,但很多都是遗留的),当独立测试时可以正常工作。特别是,某个 dynamic_cast 可以正常工作。
但是,当使用 gcc 4.1.2 和外部应用程序将该库打包用作 RHEL5 上的插件时,dynamic_cast 返回 NULL 导致应用程序无法按预期工作。在 Windows 上(使用 Visual Studio 2005 和 2008 测试 Vista 64 位)它工作正常。例如,当我使用 ddd 进行调试时,我可以看到转换前的指针具有正确的 type_name (我想像往常一样被编译器轻微损坏?)。此处的任何特定调试技巧也会有所帮助。
reinterpret_cast 解决了这个问题。虽然这肯定会受到阻碍,但我不知道如何进行,尤其是。因为这可能是由于外部应用程序的问题。这是一个令人费解的混乱,几乎看起来是徒劳的,但如果它可以帮助这里有一些示例代码。下面的 C++ 片段创建了一个“smart_handle”来对存储在字符串“input”中的某些 python 命令进行排队。字符串 IMPORT 导入一些函数的位置和定义,这些函数在函数调用 py_api::execute_py_command 中被 boost::python::exec(..) 调用:
boost::shared_ptr<my_base_class>
processor(new my_derived_class());
std::map<std::string, smart_handle> context;
context.insert(std::make_pair<std::string, smart_handle>("default_queue",
make_smart_handle(processor)));
const std::string py_command =
IMPORT +
"namesp.dialects.cpython.set_command_queue('default', default_queue)\n" +
input;
if( !py_api::execute_py_command(py_command, context) ) {
return false;
}
make_smart_handle 定义为:
template <typename type_t>
const smart_handle make_smart_handle(const boost::shared_ptr<type_t>& ptr) {
if( !ptr ) {
return smart_handle();
}
return smart_handle(new detail::smart_handle_weak_impl<type_t>(ptr));
}
函数 set_command_queue 在 python __init__.py 中定义为:
import func1
import func2
import func3
import func4
COMMAND_QUEUE_MAP = {}
def set_command_queue(queue_name, object):
COMMAND_QUEUE_MAP[queue_name] = object
def get_command_queue(queue_name = 'default'):
return COMMAND_QUEUE_MAP[queue_name]
现在,在单独的 python 文件中定义的实际 python 函数 func1、func2 等调用命名空间“namesp”下定义的 C++ 函数。这些 C++ 函数的第一行是通过以下方式将“smart_handle”恢复到“queue”:
boost::shared_ptr<my_base_class> queue = smart_handle_cast<my_base_class>(handle).lock();
正是在上述函数 smart_handle_cast 中,当库用作外部应用程序中的插件时,使用了返回 NULL 的 dynamic_cast。使用 reinterpret_cast 可以使其正常工作。smart_handle_cast 返回一个 const boost::weak_ptr。对于那些感兴趣的人,这里是 smart_handle_cast<..>() 函数的定义:
template <typename type_t>
const boost::weak_ptr<type_t> smart_handle_cast(const smart_handle& handle, bool
throw_if_failure) {
if( !handle.is_valid() ) {
if( throw_if_failure ) {
throw smart_handle::bad_handle("Bad handle, attempting to access an invalid
handle");
}
//-No throw version returns a non-initialized weak pointer
return boost::weak_ptr<type_t>();
}
//-This line fails at run time and returns null.
const detail::smart_handle_weak_impl<type_t>* casted = dynamic_cast<const
detail::smart_handle_weak_impl<type_t>* >(handle.impl());
if( !casted ) {
if( throw_if_failure ) {
throw smart_handle::bad_handle_cast("Bad handle cast, attempting to \
convert to incorrect pointee type");
}
//-No throw version returns a non-initialized weak pointer
return boost::weak_ptr<type_t>();
}
return casted->pointee;
}