C++ 调用python脚本,无需解释器

       

          在一个偶然的机会下,今年元旦(2015/01/01),才开始正式接触python这门优雅的语言.那时,协助公司的测试部修改一些测试脚本,边看脚本边学习边修改。不得不说,python优雅得体,容易上手。大约改了两周,协助任务完成,python也丢弃一旁了。

        直到前几天,2015/04/15晚上,看到部门几个开发组长在讨论,我们的产品购买的第三方库,某个功能无法实现,而我们购买那家第三方库的公司,只提供了一个python脚本,尽管此python脚本能实现功能,但是我们部门均没有接触过python(唯一会python的测试开发人员请产假了,囧)。最可怕的是,2015/04/20需要给客户演示此功能,真是伤不起,完全没有时间去把python修改为C++。

         而我恰好,曾经用过python,提议把该python封装成C/C++接口。开发组长一致认同,就由我来把脚本封装成C接口。在此之前没有做过C++调用python,完全没有想到后续的麻烦。


         C++调用python脚本,其实并不难。网上一搜一大把教程啊,简单易懂。http://www.360doc.com/content/14/0217/09/13084517_353130057.shtml       

         VC下写了个demo,很是方便,但是,Debug版本和Release版本略有差异。Debug版本用的是pythonxx_d.lib,而Release版本用的是pythonxx.lib。python解释器无pythonxx_d.lib


         只需修改python的include目录下的pyconfig.h,将pragma comment(lib,"python27_d.lib")修改为pragma comment(lib,"python27.lib"),同时,注销 ifdef _DEBUG    define Py_DEBUG      endif。


          封装完成之后,问题才真的来了:调用python脚本,需要python解释器,这个真的是让人无语,如果我调用一下python脚本,那么我们的产品也要同时打包发布python解释器?这个增加产品体积不说,也会降低用户体验。网上搜了很多这方面的解决方案,也在很多交流群里询问,都没有给出答案。

         有提出替代方案的,把python脚本打包成exe,这样无需发布解释器。这个确实也是个备份方案。但是这样会同时增加开发工作,同时,让程序去调用exe,有需要涉及一些进程通信,而我实在是无力修改python脚本,该脚本各种协议和硬编码,很是头疼。

          本着死马当活马医的心态,尝试了一下把python打包成exe,此方法也很是简单,用py2exe,同样网上一搜一大把教程:http://blog.chinaunix.net/uid-25979788-id-3064613.html


         打包完成以后,我发现产生了一个library.zip文件,解压缩后,里面一堆pyc文件。脑洞大开的时候到了,为什么产生exe之后就可以不用python解释器了呢, 而C++调用脚本就必须要python解释器呢?其实这个library.zip就相当于是裁剪python解释器,而我调用py脚本也可以这样来裁剪解释器。于是我写个demo程序,把这些pyc文件靠到工程里面,Debug的时候,报错:ImportError:No module named site,然后我就把site.py放到工程目录,再次Debug又报错:ImportError:No module named sysconfig,再把sysconfig.py放到工程目录,此时Debug成功了,裁剪解释器成功了。


        总结一下:此时调用py脚本的依赖库如下:1、_ctypes.pyd,2、pythonXX.dll,3、各种pyc文件,可打包成library.zip文件。我用到的library.zip仅为414KB。

        后续,希望可以好好的理解一下python的解释器,python太过优雅,完全吸引了我。


开发环境为VS2008+Python27

后续学习任重道远,此为本人第一篇原创技术博客,记录工作学习所获所得,以后多多学习多多记录,勉之。



ZhaiPillary

2015/04/18
### 如何在C++调用Python脚本 要在C++程序中调用Python脚本,可以通过多种方法实现。以下是几种常见的技术及其对应的示例代码。 #### 方法一:使用Boost.Python库 通过安装并配置`Boost.Python`库,可以在C++中轻松调用Python脚本。以下是一个简单的例子: ```cpp #include <boost/python.hpp> int main() { // 初始化 Python 环境 Py_Initialize(); try { // 导入 Python 脚本 boost::python::object script = boost::python::import("script"); // 调用 Python 中的函数 script.attr("some_function")(); } catch (boost::python::error_already_set const&) { PyErr_Print(); } // 结束 Python 环境 Py_Finalize(); return 0; } ``` 这种方法依赖于`Boost.Python`库的支持[^1]。 --- #### 方法二:直接使用Python嵌入API 如果不想引入额外的第三方库,可以直接利用Python提供的嵌入API来完成任务。以下是一段示例代码: ```cpp #include <Python.h> #include <iostream> int main() { // 初始化 Python 解释器 Py_Initialize(); // 添加当前目录到 Python 的模块搜索路径 PyRun_SimpleString("import sys"); PyRun_SimpleString("sys.path.append('./')"); // 加载 Python 模块 PyObject* pModule = PyImport_ImportModule("mytest"); // 替换为实际的 Python 文件名(不带.py扩展) if (!pModule) { std::cerr << "Failed to load the module." << std::endl; return -1; } // 获取指定的函数对象 PyObject* pFunc = PyObject_GetAttrString(pModule, "function_name"); // 替换为实际的函数名 if (!pFunc || !PyCallable_Check(pFunc)) { std::cerr << "Cannot find function 'function_name' in the module." << std::endl; Py_DECREF(pModule); return -1; } // 调用函数(无参数情况) PyObject_CallObject(pFunc, nullptr); // 清理资源 Py_XDECREF(pFunc); Py_DECREF(pModule); // 关闭 Python 解释器 Py_Finalize(); return 0; } ``` 这段代码展示了如何加载一个名为`mytest`的Python模块,并调用其中的一个函数[^4]。 --- #### 方法三:基于Qt框架的方式 如果你正在使用Qt框架开发应用程序,则可以借助其功能设置自定义的Python环境。具体操作包括复制所需的Python环境文件以及调整代码逻辑。例如,在模板项目中创建特定目录并将必要文件放置于此处以便正确初始化解释器[^3]。 注意此方案适用于已经集成Qt工具链的情况;对于纯命令行应用可能并不适用。 --- ### 总结 以上三种方式分别适合不同的场景需求——从轻量级的标准接口到强大的跨语言绑定支持都有涉及。开发者可以根据项目的具体情况选择最适合的技术路线实施解决方案。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值