导入 Swig 生成的包装器时 Python 挂起
当我尝试将 C++ 共享库导入到 Windows 版本的 python 2.5 中时,Python 处于“挂起”状态,我不知道为什么。
在 Linux 上,一切正常。 我们可以编译所有 C++ 代码,生成 swig 包装类。 它们可以在 python 2.5 或 2.6 中编译并导入和使用。 现在,我们正在尝试使用 Cygwin 将代码移植到 Windows。
我们可以使用 -mno-cygwin 将每个 C++ 库编译为共享 dll,这消除了对 cygwin1.dll 的依赖。 本质上,这会导致 gcc 目标成为 MinGW 而不是 Cygwin,从而使生成的二进制文件能够在 Windows 中运行,而不依赖于 Cygwin。 此外,每个共享库都可以链接到 C++ 二进制文件并成功运行。
完成此操作后,我们使用 swig 为每个共享库生成包装器。 这些包装器的生成、编译和链接都没有问题。
下一步是将生成的 python 包装器导入到 python 中。 我们可以导入除两个库之外的所有库。 对于两个不起作用的情况,当我们尝试将 .py 或 .pyd 文件导入 Windows python(使用 Visual C++ 编译的版本)时,python 挂起。 我们无法使用 ctrl+c 或 ctrl+d 杀死 python,唯一的办法是通过任务管理器杀死它。 如果我们将 gdb 附加到 python 进程并打印堆栈跟踪,我们得到的大多是垃圾,没有任何用处。
接下来,我们尝试 ifdef'ing 出 *.i 文件中的代码块并重新创建 swig 包装器。 这个过程至少允许我将库导入到 Windows python 中,但问题是我们必须注释掉太多软件运行所需的函数。 一般来说,必须注释掉三种类型的函数:静态函数、虚 const 函数和未声明为 const 的常规公共函数。 这也是可重现的,如果我们取消注释这些函数中的任何一个,那么导入会再次挂起。
接下来,我们尝试将函数提取到一个简单的 hello world 程序中,生成一个 swig 包装器并将它们导入到 python 中。 这有效。 我们完全从头文件中复制了函数。 它们在非常小的测试程序中工作,但不能在较大的共享库中工作。 我们正在以完全相同的方式构建它们。
因此,任何关于为什么会发生这种情况的想法,甚至更好的调试技术都会非常有帮助。
这些在使用 gcc 3 和 4 以及 python 2.5 和 2.6 的 Linux 上运行良好。 在 Windows 上,这是我正在使用的软件: 海湾合作委员会 3.4.4 swig 1.39(来自 swig.org 的 Windows 二进制文件) python 2.5.4(Windows 二进制文件和来自 python.org 的 include/libs)
这些是我用来构建简单的 hello world 程序的命令(完整的库使用相同的选项,只是由于额外的 -I 而更长, -L 和 -l 选项)
swig -c++ -python -o test_wrap.cc test.i
gcc -c -mno-cygwin test.cc
gcc -c -mno-cygwin test_wrap.cc -I/usr/python25/include
dlltool --export-all --output-def _test.def test.o
gcc -mno-cygwin -shared -s test_wrap.o test.o -L/usr/python25/libs -lpython25 -lstdc++ -o _TestModule.pyd
谢谢, 阿杰
Python is 'hanging' when I try to import a c++ shared library into the windows version of python 2.5 and I have no clue why.
On Linux, everything works fine. We can compile all of our C++ code, generate swig wrapper classes. They compile and can be imported and used in either python 2.5 or 2.6. Now, we are trying to port the code to Windows using Cygwin.
We are able to compile each of the C++ libraries to shared dlls using -mno-cygwin, which removes the dependency on cygwin1.dll. Essentially this causes the gcc target to be MinGW instead of Cygwin, enabling the resulting binaries to be run in Windows without any dependency on Cygwin. Moreover, each of these shared libraries can be linked into c++ binaries and run successfully.
Once this one done, we used swig to generate wrappers for each of the shared libraries. These wrappers are generated, compiled, and linked without problem.
The next step then, was to import the generated python wrapper into python. We are able to import all but two of our libraries. For the two that do not work, when we try to import either the .py or .pyd files into Windows python (the version compiled with Visual C++), python hangs. We cannot kill python with ctrl+c or ctrl+d, the only recourse is to kill it via task manager. If we attach gdb to the python process and print a stack trace, we mostly get garbage, nothing useful.
Next, we tried ifdef'ing out blocks of code in the *.i files and recreating the swig wrappers. This process at least allowed me to import the libraries into Windows python, but the problem is we had to comment out too many functions which are necessary for the software to run. In general, there were three types of functions that had to be commented out: static functions, virtual const functions, and regular public functions that were NOT declared as const. This is reproducible too, if we uncomment any one of these functions, then the import hangs again.
Next, we tried extracting the functions into a simple hello world program, generate a swig wrapper and import them into python. This worked. We copied functions exactly from the header files. They work in the very small test program, but not in the larger shared library. We are building them the exact same way.
So, any ideas about why this is happening or even just better debugging techniques would be very helpful.
These work fine on Linux with gcc 3 and 4 and python 2.5 and 2.6.
On Windows, this is the software I am using:
gcc 3.4.4
swig 1.39 (Windows binaries from swig.org)
python 2.5.4 (Windows binaries and includes/libs from python.org)
These are the commands I am using for building the simple hello world program (the full library uses the same options, it's just a lot longer because of extra -I, -L, and -l options)
swig -c++ -python -o test_wrap.cc test.i
gcc -c -mno-cygwin test.cc
gcc -c -mno-cygwin test_wrap.cc -I/usr/python25/include
dlltool --export-all --output-def _test.def test.o
gcc -mno-cygwin -shared -s test_wrap.o test.o -L/usr/python25/libs -lpython25 -lstdc++ -o _TestModule.pyd
Thanks,
AJ
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我使用的一种技术是在模块 init 函数中插入一个“硬”断点 (
__asm int 3
)。 然后,要么通过调试器运行它,要么只是运行它并让 Windows 调试器在调用中断时弹出。您可以在此处从 Microsoft 下载一个不错的 Windows 调试器。
A technique I've used is to insert a "hard" breakpoint (
__asm int 3
) in the module init function. Then either run it through a debugger or just run it and let the windows debugger pop when the interrupt is called.You can download a nice windows debugger from Microsoft here.