c 调用python clion_Python源码在Win下和Linux下的编译,C++调用Python库绘制等高线

目录

前言 Python源码以及VS2017的准备 Python源码 VS2017 Windows下编译Python源码 编译命令 编译步骤 编译后的配置 添加注册表 Win10中编译Python源码小结 Windows中C++调用Python代码绘制等高线图 CMakeLists.txt文件如下: Python代码如下: CPP文件: 运行结果 Linux中编译Python源码

前言

距离上次推送已经快一个月了,这段时间一直在准备开题。说起来我自己都不太相信,我竟然一个多学期没看过文献…….今年5月底才开始看文献,中间课题方向也被换了好几次。今天下午刚开完组会,又得改一堆。

前阵子我老师要我用C++做个软件(还没做完),其中需要有一项功能是显示一个等高线图,但是没找着可以画等高线的C++库,自己开发太麻烦了(主要自己不会)。画等高线用MATLAB很容易就能画出来,Python的matplotlib库画等高线图也很简单。所以就考虑C++调用MATLAB,或者C++调用Python。

  • 如果用C++调用MATLAB的话,打包后还需要MATLAB的运行时库才行,而且这个还很大,好像安装好后有几个G,而且美国又在对中国限制matlab,所以打算放弃C++调用MATLAB。

  • C++调用Python的话,坑会比较多,一般低级语言调用高级语言的坑都比较多。需要编译Python的源代码(Python的源码基本都是C文件),如果不编译的话可能会无法调用和Python有关的.dll文件或者.pyd文件以及相关的.lib库文件。这些都是经过编译器编译出来的,必须要保证编译器是一致的才能使用,还有需要明确是32位的还是64位的。

Note:本次推送中有部分内容是取自于我学习 夏曹俊 老师课程时所记的笔记,夏曹俊老师的课程质量还是很好的,有兴趣的可以上51cto或者网易云课堂搜索一下看看。

Python源码以及VS2017的准备

Python源码

可以直接去官网:www.python.org 上下载

caf821d9f3690d14373033088385efd6.png

6dcaabf4ae578de72a7bc5ad4f5cb1eb.png

0ba5b916474e06db3095eff786887e0c.png

解压后打开其中的目录结构如下:

de46f2a86a0a49fdffa622edb6c94260.png

VS2017

需要用VS2017来编译Python源码,VS2015得单独安装Win10开发工具,更高版本的就不清楚了,反正我还是建议使用VS2017,我这有一个企业版的2017:

链接:https://pan.baidu.com/s/1cLqLnEr9Apx5WUFqyllXBQ
提取码:46zw

具体的安装可以看看我之前写的VS2017编译Qt源码的那篇推送:搭建VS2017_QT_MATLAB开发环境。

实际上我主要是需要VS2017的nmake这个编译器,这个VS2017的编译器可以直接被我的CLion检测到,但是我的CLion找不到VS2015编译器在哪,自己手动加了也不行。

Windows下编译Python源码

编译命令
build -c Release -p x64

or

build -c Release -p win32

or

build -c Debug -p x64

or

build -c Debug -p win32
  • 前两个都是用来编译Release版本的,一个是x64(amd64)平台的,一个是win32平台的。我编译的都是x64的。

  • 后两个都是用来编译Debug版本的,一个是x64(amd64)平台的,一个是win32平台的。我编译的都是x64的。

  • -c 表示编译模式,-p是指平台(platform)

下面仅以build -c Release -p x64为例。

编译步骤
  • 先把下面的这个目录添加到环境变量中,因为编译的过程中可能会用到Win10的开发工具,为了能让编译器找到它们,所以需要添加到路径中:

C:\Program Files (x86)\Windows Kits\10\bin\10.0.17134.0\x64

上面的这个10.0.17134.0只是win10开发工具的一个版本,不一定要和我的一致,如果有多个版本,选择最新的就行。

  • 进入PCbuild文件夹中,这是Windows环境的源码目录,如下:
    可以看到这里面都是VS的项目文件

    cab6d0aef3e133263f8b3b7691b3536f.png

  • 在当前文件夹中打开WindowsPowerShell,或者打开CMD用cd命令切换到PCbuild文件夹下,在其中输入下面这行编译指令来编译64位的Python:

./build -c Release -p x64

5e331f146ad934a207b9c49570ad75bb.png

编译过程的第一步是去下载编译依赖的库和文件,一般情况下下载都会出点错吧,毕竟是从国外的服务器上下载的。这个下载下来的东西都放在源码路径/externals文件夹下:

af4c2d569583f7c5898aa28b82a267de.png

这个externals文件夹开始时是不存在的,执行编译指令后才会被创建

c57637ba7380781c841704cb52d5b864.png

这个externals文件,我已经上传到云盘里了,如果有同学上面没下载下来的话可以下载我上传的这个,解压后放到下载的源码路径下,记得不要改externals这个名字:

链接:https://pan.baidu.com/s/1EgPjkcfFtTf1jCC_geYF6g
提取码:depz

拷贝好后再重新编译就能成功了,如下图:

ef1614a6982ac3c0ce0312ec2e0001dd.png

Note:build -c Release -p x64编译输出在./PCbulid/amd64文件夹中,这个文件夹中就有一个python.exe,如下图

edeeaf72d6f02e9ca85ae37fa82fce99.png

编译后的配置
  • 添加一个PYTHONHOME系统变量,值为源码的家目录,如下图(我把源码拷贝到C盘了)

c40ad435cc3158db20a411d39d4d29b4.png

  • 在系统环境变量中把编译出来的python.exe的路径添加进去

    3d5743ff470804e28170e5635267936a.png

  • 还有pip的路径也添加进去,你的pip可以用externals/pythonx86/tools/Scripts中的,所以还应该把这个路径添加到环境变量中

    634333cbe13d770d0802613f0de91c64.png

Note:如果有多个版本的Python的话,在用到Python.exe时,使用的是PATH环境变量中最上面的那个版本的Python。

添加注册表

在用Python做拓展库时,它拓展库可以打成一个安装包,这个安装包会通过注册表来判断你的系统有没有装这个版本的Python。

下面给出一段Python代码来添加注册表:

import sys
from winreg import *


version = sys.version[:3]
installpath = sys.prefix
regpath = "SOFTWARE\\Python\\Pythoncore\\%s-64\\" % (version)
installkey = "InstallPath"
pythonkey = "PythonPath"
pythonpath = "%s;%s\\Lib\\;%s\\DLLs" % (installpath, installpath, installpath)

print(version)


def RegisterPy():
    try:
        reg = OpenKey(HKEY_CURRENT_USER, regpath)
    except EnvironmentError as e:
        try:
            reg = CreateKey(HKEY_CURRENT_USER, regpath)
            SetValue(reg, installkey, REG_SZ, installpath)
            SetValue(reg, pythonkey, REG_SZ, pythonpath)
            CloseKey(reg)
        except:
            print("---Python ", version, " is not registered!")
            return
    if (QueryValue(reg, installkey) == installpath) and (QueryValue(reg, pythonkey) == pythonpath):
        CloseKey(reg)
        print("---Python ", version, " is already registered!")
        return
    CloseKey(reg)


if __name__ == "__main__":
    RegisterPy()

Note: 一定要用你编译出来的那个版本的Python来运行这个代码!

Win10中编译Python源码小结

到此,在Win中的编译就算完事了,上面说了这老大一堆,实际总结下来也没多少

  • python官网下载源码,下载VS2017

  • 把Windows Kits中的那个x64目录添加到路径(具体路径往回翻一下看看)

  • 进入源码目录下的PCbuild目录中,在当前目录中打开Power Shell或者打开cmd然后cd到PCbuild目录中

  • 执行./build -c Release -p x64编译出64位Release版本的Python,python.exe在PCbuild目录中的amd64下面。(可以先下载我上传的那个externals文件夹,解压后放到源码根目录下)

  • 编译完成后添加PYTHONHOME系统变量,并把PCbuild/amd64这个目录添加到环境变量中

  • 添加注册表

如果想编译32位的只要把x64改成win32就行。过程都一样,那个Python代码中的64也改成32。

Windows中C++调用Python代码绘制等高线图

这部分不涉及C++与Python之间的参数传递,仅仅是C++调用py文件,py文件也没有编译。有关C++与Python之间的数据传递,后期会做一些推送来记录。

  • 把Python源码目录中的Include拷贝到程序目录中

  • 把Python源码目录中的PC/pyconfig.h拷贝到程序目录中(放到上面的Include里面)

  • 把PCbuild/amd64/python37.lib,还有相应的python37.dll也拷贝到程序目录中。除此之外还需要从这个amd64下面拷贝出:_bz2.lib、_contextvars.lib、_socket.lib、_tkinter.lib、select.lib、unicodedata.lib,以及对应的.pyd文件(pyd文件是Python编译的动态库也要和.exe放一起)。实际上你可以把amd64下的整个都拷贝走,这样更省事,就是打包后的文件大一点,事先我们也不知道需要哪些库,但是如果缺少库的话,运行结果会提示缺少那个,此时你再去amd64中找(下同)

  • 把Python源码目录中的Lib目录也整个拷贝走,如果不怕麻烦可以挨个删掉用不上的库。

采用CLion创建的项目,项目文件结构如下:

17ceb5b52e4dda3bfe392e0b87eb3522.png

我把python相关的lib库文件和头文件都放在Python子文件夹中,把pyd以及dll文件以及py源代码都和.exe文件放在一起。

CMakeLists.txt文件如下:
cmake_minimum_required(VERSION 3.15)
project(demo8_2)

set(CMAKE_CXX_STANDARD 14)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)

# CLion这无法用相对路径
# 把Armadillo的头文件的目录包括进来(固定的)
include_directories("D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python/Include")

# 把Python lib 目录路径 链接进来
link_directories("D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python")
# 链接 Python liblink_libraries("D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python/_bz2.lib""D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python/_contextvars.lib""D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python/_socket.lib""D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python/_tkinter.lib""D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python/python37.lib""D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python/select.lib""D:/PersonalAllAboutStudy/Programming/CLion_Python_Demo/demo8_2/Python/unicodedata.lib"
)add_executable(main main.cpp)

不可照搬,起码得改个路径啥的!

Python代码如下:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl


# 隐藏matplotlib的工具栏
mpl.rcParams['toolbar'] = 'None'


# 修改matplotlib窗口的图标
thismanager = plt.get_current_fig_manager()
# thismanager.window.wm_iconbitmap("could.png")  # 试了,看不到图标
thismanager.window.wm_iconbitmap("")  # 换成Tkinter的羽毛把


# 计算x,y坐标对应的高度值
def f(x, y):
    return (1-x/2+x**5+y**3) * np.exp(-x**2-y**2)


def main():
    # 生成x,y的数据
    n = 256
    x = np.linspace(-3, 3, n)
    y = np.linspace(-3, 3, n)

    # 把x,y数据生成mesh网格状的数据,因为等高线的显示是在网格的基础上添加上高度值
    X, Y = np.meshgrid(x, y)

    # 填充等高线
    plt.contourf(X, Y, f(X, Y), 20, cmap=plt.cm.hot)
    # 添加等高线
    C = plt.contour(X, Y, f(X, Y), 20)
    plt.clabel(C, inline=True, fontsize=12)
    # 显示图表
    plt.show()


if __name__ == '__main__':
    main()
CPP文件:
#include 
#include 
#include 
using namespace std;
int main(int argc, char *argv[]){
    cout <"C++ call Python" <endl;

    //设置Python的Home路径
    Py_SetPythonHome(L"./");

    //python解释器初始化
    Py_Initialize();

    try
    {
        int re = 0;
        

        // 执行python文件
        char *filename = "a.py";
        FILE *fp = fopen(filename,"r");
        if (!fp)
        {
            throw exception("open file failed!");
        }
        re = PyRun_AnyFile(fp, filename);
        if (re != 0)
        {
            PyErr_Print();
            throw exception("PyRun_AnyFile failed!");
        }

        //清理python
        Py_Finalize();
    }
    catch (exception &ex)
    {
        cout <endl;
        Py_Finalize();
    }
    getchar();
    getchar();
    return 0;
}
运行结果

5c70e5e0c990d0efe97bb4353b5f65fa.png

Linux中编译Python源码

这块我是直接用我的云服务器来演示的,就不写程序来演示了,直接给出编译步骤,也不截图了。

安装依赖项

命令行中分别输入以下几行

sudo apt-get install g++ make git

sudo apt-get install libbz2-dev libncurses5-dev  libgdbm-dev liblzma-dev libsqlite3-dev libssl-dev libreadline6-dev

sudo apt-get install libffi-dev zlib*

下载Python源码并解压
这部分同上面一样,略,下面只给出解压命令

tar -xvf xxxx.tar.xz

编译python

进入源码目录,分别执行下面几行指令

./configure -h

./configure --enable-shared

make -j2

make install

其中,make -j2是采用2个线程编译

覆盖原来的Python

还是在Python源码目录中,

cp libpython3.7m.* /usr/lib

cp /usr/local/bin/python3.7 ./usr/bin/python

验证下Python的版本

命令行中输入:

python -V
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值