要在我的cpp应用程序中嵌入python,我在Windows上使用VS2017的MSVC v141(MSV v.1916 32位)编译了cpython 3.7.3。 生成的代码位于PCBuild / win32中。
应用程序需要修改sys.path
才能从应用程序目录的子文件夹中找到模块。那是我注意到无法解释的崩溃的地方。以下脚本在第一次运行时有效,但在第二次运行时无效。第二次运行使应用程序崩溃。这与import
语句有关。我可以轻松地调用真正的opencv函数,但将其作为最小示例删除了。
此外,如果我从搜索路径中删除C:\Python\cpython3.7.3\PCbuild\win32
,该脚本也不会崩溃,但是该脚本当然不会执行应有的作用。
#!/usr/bin/env python3
import sys
sys.path = ['', 'C:\Python\cpython3.7.3', 'C:\Python\cpython3.7.3\Lib', 'C:\Python\cpython3.7.3\PCbuild\win32', 'C:\Python\cpython3.7.3\Lib\site-packages']
import cv2 # crash on 2nd run
import numpy # crash on 2nd run
import os # always works
import glob # always works
不幸的是,我无法在运行python时调试应用程序,因为python由于缺少编码而无法初始化。仅释放模式有效。 似乎内置模块有效,而通过pip(文件夹站点软件包)下载的模块无效。
步骤
build.bat :(发布版本;为调试添加-d)
cd cpython3.7.3
cd PCbuild
cmd /c build.bat
pause
为了执行脚本,我创建了这个最小的示例。这不是我的原始代码,但是在第二次运行时也会崩溃,我希望原因是相同的。
main.cpp
#include <Python.h>
#include <fstream>
#include <sstream>
#include <string>
int runScript(const std::string &script){
const char *script_ = {script.c_str()};
Py_Initialize();
PyRun_SimpleString(script_);
Py_Finalize();
return 0;
}
int main(int argc, char *argv[])
{
std::string scriptpath = "C:\\temp\\import_crash_on_2nd_run.py";
std::ifstream t(scriptpath);
std::stringstream buffer;
buffer << t.rdbuf();
// maxCount=2 -> crash
int maxCount = 1;
for ( int count = 0; count < maxCount; count++ ){
runScript(buffer.str());
}
}
更新:
这是一个错误。 https://github.com/numpy/numpy/issues/8097的某人注意到,如果您不致电Py_Finalize
,它在连续导入时不会崩溃。完全没有。从使用的库中不确定这是python的错误还是质量差。