Python与C++混合编程


写在前面

今天在CSDN看到某个算法(约瑟夫生死者游戏)的三种写法,分别是C、C++、Python,我分别实现后产生了一种想法,既然Python被称为胶水语言,那么应该可以把Python移植到C++中执行,说干就干!

三种版本

C语言版(ysfc.cpp),在vs2019中使用cpp后缀

#include<stdio.h>

void ysfc()
{
    int i = 1;
    int j = 0;
    int c = 0;
    int a[30] = { 0 };
    int b[30] = { 0 };
    while (i <= 31)
    {
        if (i == 31)
        {
            i = 1;
        }
        else if (c == 15)
        {
            break;
        }
        else 
        {
            if (b[i - 1] != 0)
            {
                i++;
                continue;
            }
            else
            {
                j++;
                if (j != 9)
                {
                    i++;
                    continue;
                }
                else
                {
                    b[i - 1] = 1;
                    a[i - 1] = j;
                    j = 0;
                    printf("第%d号下船了\n", i);
                    i++;
                    c++;
                }
            }
        }
    }
}

C++版(ysfcpp.cpp)

#include<iostream>
using namespace std;
void ysfcpp()
{
    int i = 1;
    int j = 0;
    int c = 0;
    int a[30] = { 0 };
    int b[30] = { 0 };
    while (i <= 31)
    {
        if (i == 31)
        {
            i = 1;
            continue;
        }
        else if (c == 15)
        {
            break;
        }
        else
        {
            {
                if (b[i - 1] != 0)
                {
                    i++;
                    continue;
                }
                else
                {
                    j++;
                    if (j != 9)
                    {
                        i++;
                        continue;
                    }
                    else
                    {
                        b[i - 1] = 1;
                        a[i - 1] = j;
                        cout << "第" << i << "号下船了" << endl;
                        j = 0;
                        c++;
                        i++;
                    }
                }
            }
        }
    }
}

Python版(ysf.py)

#预先将arg设置为None
def ysf(arg = None):
    people = [0]*30
    i = 1
    check = 0
    p = 0
    while i <= 31:
        if i == 31:
            i = 1
        elif p == 15:
            break
        else:
            if people[i - 1] != 0:
                i += 1
                continue
            else:
                check += 1
                if check == 9:
                    print("第%d号下船了" % i)
                    people[i - 1] = 1
                    check = 0
                    i += 1
                    p += 1
                else:
                    i += 1
                    continue
    #是否传递返回值可以根据需要修改
    if arg:
        return arg

配置环境

注意修改属性时的平台和配置要与调试窗口保持一致,即Release对应Release,x64对应x64(Debug与x86同理)。


新建vs2019解决方案,在“属性->VC++目录”中添加包含目录和库目录,将Python安装目录下的include目录添加到包含目录,再把python下libs目录添加到库目录(Debug模式下需要python3x_d.lib,一般情况下libs目录下是没有的,修改python3x.lib名字即可)。


如果要向python函数传递中文参数,需要在C++项目中添加如下代码:

#pragma execution_character_set("utf-8")

main函数

#include<iostream>
#include<stdio.h>
//引用Python头文件
#include "Python.h"
using namespace std;
void ysfc();
void ysfcpp();
int main()
{
    cout << "C语言版" << endl;
    ysfc();
    cout << endl;

    cout << "C++版" << endl;
    ysfcpp();
    cout << endl;
    //初始化Python
    Py_Initialize();
    if (!Py_IsInitialized())
    {
        cout << "初始化失败!" << endl;
        //释放Python
        Py_Finalize();
    }
    //三个python类
    PyObject* pMoudle;
    PyObject* pFunc = NULL;
    PyObject* pArg = NULL;
    //导入sys包
    PyRun_SimpleString("import sys");
    //添加路径(与cpp文件路径一致)
    PyRun_SimpleString("sys.path.append('./')");
    //加载python文件,括号内为文件名,不需要扩展名
    pMoudle = PyImport_ImportModule("ysf");
    if (!pMoudle)
    {
        cout << "py文件导入失败" << endl;
        Py_Finalize();
    }
    else
    {
        //加载py文件中的函数
        pFunc = PyObject_GetAttrString(pMoudle, "ysf");
        if (!pFunc)
        {
            cout << "函数导入失败" << endl;
            Py_Finalize();
        }
        else
        {
            cout << "Python版" << endl;
            /*
            调用函数,第二个参数为向python函数传递的参数
            必须为Pyobject类型,不需要参数时设置为NULL
            如果要传递参数或接收返回值,可以参考后面注释掉的部分
            */
            PyEval_CallObject(pFunc,(PyObject*)NULL);
            system("pause");
            /*
            //定义一个传递返回值的C++变量
            char* result;
            //把要传递给python函数的参数从char类型转变为python的str类型
            PyObject* pyParams = Py_BuildValue("(s)","helllo world!");
            //调用函数,用Pyobject变量接收返回值
            pArg = PyEval_CallObject(pFunc,pyParams);
            //将返回值转变为C++的char类型,并传递给result
            PyArg_Parse(pArg, "s", &result);
            //在C++中输出返回值
            cout << result << endl;
            system("pause");
            /*
        }
    }
    //以cmd命令调用(即命令行中调用python文件)
    //system("python ysf.py");
}

写在后面

在实际应用中,混合编程会有一定的用处,本文简单的阐述用法。