win10+VS2022+c++调用python封装的pyd库保姆级教程

python有py、pyc、pyw、pyo、pyd等文件格式,其中除了py的其他格式都起到了不暴露源码的作用,但是pyc、pyw、pyo容易被反编译,所以就剩pyd格式,该文件格式不会被反编译。本文将py文件生成pyd文件,并通过c++调用的具体过程进行介绍。

一、准备环境

1、Microsoft Visual Studio(2019或者2022都可以),没有安装过的看这里,传送门
2、安装过anaconda3,没有安装过的看这里,传送门
3、只安装对应的VS和anaconda3软件,不安装其他环境(记住anaconda3的安装目录,比如我的安装目录在D:\Users\WDX\anaconda3)
4、网络良好

二、通过anaconda安装虚拟环境

1、点击电脑左下角的开始,然后再搜索栏中输入Anaconda Prompt,找到该应用,点击打开。

在这里插入图片描述

2、打开后,按照这篇文章中的anaconda操作方式创建新的虚拟环境,或者自己输入如下指令,名字为runLib(根据自己的需求),python环境为3.8。
conda create -n runLib python=3.8
3、然后等待环境创建,出现" Processed([y]/n)?",输入“y”;等待环境创建成功。

在这里插入图片描述

4、激活环境,命令如下
conda activate runLib
5、不要关闭窗口,先放一放,进行其他操作。

三、准备python文件

1、通过pycharm或者python编译器,编写一个python脚本,文件名命名为testPy(注意不能为test,因为python内置有test.py),代码如下,这里我们导入numpy第三方包。(一会通过anaconda安装这个包)
import sys
import numpy as np
print('enter python success') 

def Hello():
    print("Hello, world")
def test_cpp2py(data):
    data_after_np = np.array(data)
    print('successful, and data is: ', data_after_np)  # 输出
    return [1, 2, 3, 4]  

if __name__ == "__main__":
    Hello()
    data = [6,6,6,6]
    test_cpp2py(data)


2、再创建一个python文件,命名为setup,这里我们导入Cython包,(一会通过anaconda安装这个包)代码如下
from setuptools import setup
from Cython.Build import cythonize
 
setup(
    ext_modules=cythonize("testPy.py")  # 这里改为你要打包成.pyd文件的py文件路径
)

3、假如我刚才创建的文件路径在,这个里面。

在这里插入图片描述

4、重点来了,打开第二步打开的命令窗口,在窗口中输入E:,(因为我的文件在E:\code\python\pyd放着),回车。当变成下面这样时,我们再输入cd E:\code\python\pyd,如下图所示,即为已进入目录下。

在这里插入图片描述
在这里插入图片描述
5、然后输入pip install cython,安装cython库。
在这里插入图片描述

6、安装完成后,继续安装numpy第三方库,这里要注意,我们的python版本要与numpy库对应,如果直接安装,默认安装最高版本,最后再调用的时候会出现加载不上库(这是个大坑)。参考这两篇博文后,与python3.8对应的numpy版本为numpy1.18.2,需要通过下面地址下载。

博文1
博文2

下载地址:https://pypi.org/project/numpy/1.18.2/#files
在这里插入图片描述

7、下载完成后,需要进行安装。我把文件放在了F盘。所以安装的时候只需要在命令框中输入pip install F:\numpy-1.18.2-cp38-cp38-win_amd64.whl,回车.出现如下所示时,表示已正确安装。

在这里插入图片描述
在这里插入图片描述

8、然后我们需要在命令框中输入,python setup.py build_ext --inplace,回车。等待执行命令,生成.pyd文件。
python setup.py build_ext --inplace

在这里插入图片描述

在这里插入图片描述

9、改名,将testPy.cp38-win_amd64.pyd,改名成testPy.pyd。

四、编写c++调用程序

1、打开vs,创建控制台应用,选择release,x64;然后将下面代码覆盖进去。
#include <iostream>
#include <Python.h>
#include <vector>
using namespace std;


vector<int> test_param2py(vector<int> data) {

    // 在这里导入你的 .pyd 文件,注意一定不要加后缀,比如testForCpp2Py.cp310-win_amd64.pyd就写testForCpp2Py就行
    PyObject* pModule = PyImport_ImportModule("testPy");

    // 声明一个用于接收结果的数组
    vector<int> result{};

    // 下面实现对.pyd文件中的函数的操作(前提是前面的操作没问题,pModule不会是空指针
    if (pModule != nullptr) {
        PyObject* pFunc = PyObject_GetAttrString(pModule, "test_cpp2py"); // 获取函数,这里填写要调用的函数名,笔者这里是test_cpp2py
        if (pFunc && PyCallable_Check(pFunc)) { // 判断该函数是否存在且可调用

            // 创建参数,由于c++和python的类型不对应,所以要转化
            // 这里根据传入的vector类型的data来创建一个对应列表list
            PyObject* pData = PyList_New(data.size());
            for (int i = 0; i < data.size(); ++i) {
                PyList_SetItem(pData, i, PyLong_FromLong(data[i])); // 这里要对data[i]转化为python类型
            }

            // 构建一个参数列表,第一个参数为参数列表的参数数量,这里为1
            PyObject* pArgs = PyTuple_Pack(1, pData);
            // 调用该函数
            PyObject* pValue = PyObject_CallObject(pFunc, pArgs); // 调用函数
            Py_DECREF(pArgs);

            // 处理返回值
            if (pValue != nullptr) {
                ;
                // 从pValue中取值
                for (Py_ssize_t i = 0; i < PyList_Size(pValue); ++i) {
                    result.push_back(PyLong_AsLong(PyList_GetItem(pValue, i)));
                }
                Py_DECREF(pValue);
            }
            Py_DECREF(pFunc);
        }
        Py_DECREF(pModule);
    }
    else {
        // 证明有问题,pModule为空指针了
        PyErr_Print(); // 打印错误信息
    }

    return result; // 返回结果
}



int main()
{
    Py_SetPythonHome(L"./runLib");
    Py_Initialize(); // 初始化 Python 解释器


    // 检查初始化是否成功
    if (!Py_IsInitialized())
    {
        printf("初始化失败!");
        return 0;
    }


    //PyRun_SimpleString("print ('hello world')");   //ok

   // 无参无返回值
   // test_cpp2py_c();  //ok

    // 有参有返回值
    vector<int> result = test_param2py({ 100, 200, 300, 400 });
    cout << "\n返回值为:";
    for (int item : result) {
        cout << item << ' ';
    }
    cout << endl;
    
    Py_Finalize(); // 关闭 Python 解释器
    system("pause");

2、打开anaconda3的目录,找到envs,再找runLIb目录,也就是我们安装的虚拟环境。找到之后我们把include文件夹和libs文件夹复制在刚才创建的VS C++工程下。

在这里插入图片描述
在这里插入图片描述

3、右键工程,点击属性,开始配置包含目录和库目录。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、配置完成后,点击生成。找到生成的exe文件。然后我们将testPy.pyd文件、python38.dll文件放进这个目录下;其中python38.dll是在runLib文件下的python38.dll复制。最后把runLib整个文件夹放在该目录下(因为软件启动需要调用python解释器,这样我们就不需要配置环境变量)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

5、放进去之后,我们即可运行exe,如下图所示。即为运行成功。在这里插入图片描述

以上就是c++调用pyd文件的所有过程!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Dakchueng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值