简体   繁体   English

SWIG C ++ Python多态和多线程

[英]SWIG C++ Python polymorphism and multi-threading

I'm integrating a 3rd party C++ package to a python application using SWIG . 我正在使用SWIG将第三方C ++包集成到python应用程序中。 The package connects to a proprietary API over a network and receives updates. 该程序包通过网络连接到专有API并接收更新。 The overall flow is that python instantiates a C++ object, calls its functions to set it up and then waits for the updates. 整个流程是python实例化一个C ++对象,调用它的函数来设置它,然后等待更新。

I implemented a callback mechanism for the updates using SWIG's directors feature , and while testing from python, or from C++ functions called by python, it works well. 我使用SWIG的director功能为更新实现了一个回调机制,并且在从python或python调用的C ++函数进行测试时,它运行良好。 Namely I'm able to inherit a C++ class in Python, call its virtual functions from C++ and see the python code take priority and execute. 也就是说,我能够在Python中继承C ++类,从C ++调用它的虚函数,并看到python代码优先并执行。

The problem: 问题:
When I receive the updates from the network I get: 当我从网络收到更新时,我得到:

The thread 'Win32 Thread' (0x1f78) has exited with code 0 (0x0).
Unhandled exception at 0x1e0650cb in python.exe: 0xC0000005: Access violation writing location 0x0000000c.

This exception is thrown from within python27.dll while calling the callback function. 调用回调函数时, python27.dll会抛出此异常。
My suspicion is this: I've violated the GIL 我怀疑是这样的: 我违反了GIL
AFAIU the updates come from a different thread and call python's code using that thread. AFAIU更新来自不同的线程,并使用该线程调用python的代码。

At this point I'm at a loss. 在这一点上,我不知所措。 Is SWIG's director feature limited only to flows initiated within python (ie from python managed threads)? SWIG的导演功能是否仅限于在python中启动的流程(即来自python托管线程)?
How do I circumvent this? 我该如何规避这个? How do I induce updates from C++ to python? 如何引导从C ++到python的更新? Is it even possible using SWIG? 甚至可以使用SWIG吗?
Should I use a completely different approach? 我应该采用完全不同的方法吗?

I'm open for any suggestions on this matter... 我愿意接受有关此事的任何建议......

If your SWIG-wrapped C++ code invokes the callback routine in-thread, then there're probably no GIL problems - SWIG-generated code does not perform any GIL management that I've seen, which means that when Python code calls in to your C++ code, you retain the GIL throughout the call. 如果您的SWIG包装的C ++代码在线程中调用回调例程,那么可能没有GIL问题 - SWIG生成的代码不会执行我见过的任何GIL管理,这意味着当Python代码调用您的C ++代码,您在整个调用过程中保留GIL。

However, if your C++ code defers the callback to another thread, then you very likely have violated the GIL. 但是,如果您的C ++代码将回调推迟到另一个线程,那么您很可能违反了GIL。 This is simple enough to work around: Before you invoke the callback, call PyGILState_Ensure(), and when the callback completes, invoke PyGILState_Release. 这很简单,可以解决:在调用回调之前,调用PyGILState_Ensure(),当回调完成时,调用PyGILState_Release。 Refer to http://docs.python.org/c-api/init.html , the section "Non-Python created threads". 请参阅http://docs.python.org/c-api/init.html ,“非Python创建的线程”部分。 (If you're using C++ exception handling here, you might need to take extra care to ensure that you can release the GIL.) (如果您在此处使用C ++异常处理,则可能需要格外小心以确保可以释放GIL。)

If you haven't yet looked at the stack trace, it's worth verifying that that NULL pointer deref isn't something silly happening in your code. 如果你尚未查看堆栈跟踪,那么值得验证的是,NULL指针deref不是代码中发生的傻事。 (You can attach to the Python process running your code with VS/GDB/WinDBG; the Python execution will remain inscrutable, but you can trace your C++ code this way.) (您可以附加到使用VS / GDB / WinDBG运行代码的Python进程; Python执行仍然不可思议,但您可以通过这种方式跟踪C ++代码。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM