程序在 Windows 中跨 DLL 边界使用嵌入式 Python/C++ 代码崩溃

Posted

技术标签:

【中文标题】程序在 Windows 中跨 DLL 边界使用嵌入式 Python/C++ 代码崩溃【英文标题】:Program crashing with embedded Python/C++ code across DLL boundary in Windows 【发布时间】:2017-02-16 11:56:11 【问题描述】:

抱歉,帖子太长了。我已经搜索了很多,但找不到答案,所以这里是:

我正在使用 C++ (BoostPython) 开发 Python 扩展库。对于测试,我们有一个基于 Python 的测试工具,但我还想添加一个单独的 C++ 可执行文件(例如,使用 BoostUnitTest 或类似工具)以添加对库的进一步测试,包括测试不直接暴露给 Python 的功能。

我目前在 Linux 上运行它没有问题。我正在构建库,然后将其动态链接到使用 BoostUnitTest 的可执行文件。一切都按预期编译和运行。 但在 Windows 中,我遇到了问题。我认为跨 DLL 边界注册 C++->Python 类型转换器可能存在问题。 为了显示问题,我有以下示例: 在我的库中,我定义了:

namespace bp = boost::python;
namespace bn = boost::numpy;

class DLL_API DummyClass

public:
    static std::shared_ptr<DummyClass> Create()
     
        return std::make_shared<DummyClass>();
    
    static void RegisterPythonBindings();
;
void DummyClass::RegisterPythonBindings()

    bp::class_<DummyClass>("DummyClass", bp::init<>())
        ;

    bp::register_ptr_to_python< std::shared_ptr<DummyClass> >();

其中 DLL_API 是 Windows 的常用 _declspec(...)。这个想法是这个虚拟类将作为更大的 Python 模块的一部分导出,带有

BOOST_PYTHON_MODULE(module)

    DummyClass::RegisterPythonBindings();

从可执行文件中链接到我拥有的库(省略包含等):

void main()
   
    Py_Initialize();
    DummyClass::RegisterPythonBindings();
    auto myDummy = DummyClass::Create();
    auto dummyObj = bp::object( myDummy );

我在 boost::python::object 中包装 myDummy 的最后一行在 Windows 中因未处理的异常而崩溃。异常是从 Python (throw_error_already_set) 抛出的。我相信(但可能是错误的)它没有找到合适的 C++ 类型到 Python 的转换器,即使我调用了注册绑定。

KernelBase.dll!000007fefd91a06d()
msvcr110.dll!000007fef7bde92c()
TestFromMain.exe!boost::python::throw_error_already_set(void)
TestFromMain.exe!boost::python::converter::registration::to_python(void const volatile *)
TestFromMain.exe!boost::python::converter::detail::arg_to_python_base::arg_to_python_base(void const volatile *,struct boost::python::converter::registration const &)
TestFromMain.exe!main() Line 66
TestFromMain.exe!__tmainCRTStartup()
kernel32.dll!0000000077a259cd()
ntdll.dll!0000000077b5a561()

作为测试,我在 main 函数之前的可执行文件中复制了完全相同的代码来定义 DummyClass,而不是链接到 dll,这可以按预期工作。

我在边界两侧使用嵌入式 python 编译为 DLL 的模型在 Windows 中是否可行(这仅用于测试工具,所以我总是使用完全相同的工具链)。

非常感谢。

【问题讨论】:

【参考方案1】:

如果有人再次阅读此内容,Windows 中的解决方案是将 Boost 编译为动态库并动态链接所有内容。我们不得不稍微改变一下代码的结构,但它现在可以工作了。

Boost 文档中有一个(小)参考说明,在 Windows 中,Boost 的动态库版本具有一个通用类型寄存器,用于在 Python/C+ 之间进行转换。该文档没有提到静态库版本没有通用寄存器(但我现在知道它不起作用)。

【讨论】:

以上是关于程序在 Windows 中跨 DLL 边界使用嵌入式 Python/C++ 代码崩溃的主要内容,如果未能解决你的问题,请参考以下文章

将 WireGuard 嵌入到 Windows 上的 Go 应用程序中

.htaccess规则允许在Firefox中跨站点嵌入字体共享

Windows Dll InjectionProcess InjectionAPI Hook

使用 Windows 窗体移植旧的 Flash 游戏 - 如何嵌入 Flash Player dll?

在嵌入Python解释器的应用程序中调试tk85.dll中的问题

跨 DLL 边界使用单例 [重复]