Windows C++中嵌入Python脚本含import numpy等库出现问题

来源:互联网 发布:开发上位机界面软件 编辑:程序博客网 时间:2024/06/05 08:31

C++调用Python脚本

问题

在C++中调用Python脚本如果使用第三方库,如import numpy/ PIL/ scipy/ opencv/ PIL/ matplotlib等这些库文件时可能就会出现如下图所示错误:
import numpy

import numpy error

在VS中使用64位debug版,而且是debug版有问题,而release版没有问题(后来发现的release版可以正常运行)如果release版也有类似问题,那么我的方法估计不会奏效了。

现有方法

然后在国内的论坛和博客中搜了很多,但是发现只有几个提问,回答也不好,到国外的论坛网站搜索,有很多这样类似的问题,但是能正面回答的不是很多(有一些可能是我的水平低,没有懂)。最终也没有找到合适的解决方法,这个问题困扰了我大概一周的时间啊。

问题分析

最后,通过在不同环境尝试,无意发现release可以运行,而debug版不可以,那么可能的原因就是debug版的python解释器会对python脚本中包含的一些模块包解析,这个在嵌入python这个问题中是多此一举的。所以debug版并不需要将脚本解析,那么就将C++项目中即使是debug版调用的python解释器也使用release版的。

最终整体解决方案

1. 修改文件名

在Python的安装目录:\libs文件夹下,将python36.lib改为python36_d.lib,从而替换掉原有的debug版。我的Python版本是3.6.2,有些版本下好像没有debug版lib文件,我已经不记得是不是自带的debug版lib文件,具体版本号为 v3.6.2:5fd33b5,

但如果只是将文件名修改,也会在VS中产生–链接–错误:
修改python36_d.lib后产生的错误

2. 修改python/C API配置文件

产生这个错误,主要是因为python/C API配置文件中的Py_DEBUG/Py_TRACE_REFS引起, 修改目录:\include下的pyconfig.h和object.h文件:

  • 在pyconfig.h文件中:
    原代码:
#           if defined(_DEBUG)#               pragma comment(lib,"python36_d.lib")#           elif defined(Py_LIMITED_API)#               pragma comment(lib,"python3.lib")#           else#               pragma comment(lib,"python36.lib")#           endif /* _DEBUG */
修改为:
#           if defined(_DEBUG)#               pragma comment(lib,"python36.lib")#           elif defined(Py_LIMITED_API)#               pragma comment(lib,"python3.lib")#           else#               pragma comment(lib,"python36.lib")#           endif /* _DEBUG */
  • 在pyconfig.h文件中:
    原代码:
#ifdef _DEBUG#   define Py_DEBUG#endif
修改为:
#ifdef _DEBUG//# define Py_DEBUG#endif
  • 在object.h文件中:
    原代码:
/* Py_DEBUG implies Py_TRACE_REFS. */#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)#define Py_TRACE_REFS#endif
修改为:
/* Py_DEBUG implies Py_TRACE_REFS. */#if defined(Py_DEBUG) && !defined(Py_TRACE_REFS)//#define Py_TRACE_REFS#endif

后记:
去掉Py_DEBUG后可能会面临一些检查问题,比如去掉Py_Debug后就不会执行以下检查:
* Extra checks are added to the object allocator.
* Extra checks are added to the parser and compiler.
* Downcasts from wide types to narrow types are checked for loss of information.
* A number of assertions are added to the dictionary and set implementations. In addition, the set object acquires a test_c_api() method.
* Sanity checks of the input arguments are added to frame creation.
* The storage for long ints is initialized with a known invalid pattern to catch reference to uninitialized digits.
* Low-level tracing and extra exception checking are added to the runtime virtual machine.
* Extra checks are added to the memory arena implementation.
* Extra debugging is added to the thread module.

原创粉丝点击