Cmake/Gcc调用 Python模块

系统:ubuntu 18.04

安装库:

sudo apt-get install python3-dev

其他系统的安装方法
可以通过如下命令检查系统可调用的python

locate Python.h

在这里插入图片描述
这里使用最后一个,即 Python3.6

Cmake

CmakeList.txt

cmake_minimum_required(VERSION 3.0.2)
project(c_emb_python)

#set(CMAKE_CXX_STANDARD 14)
set(CMAKE_BUILD_TYPE  Debug)

# 用locate Python.h 取得头文件的位置之后可以使用 #include <Python.h>
include_directories("/usr/include/python3.6m")

# 下面这个参数通过命令行运行 python3.6-config --ldflags 获得
# -L/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu -L/usr/lib -lpython3.6m -lpthread -ldl  -lutil -lm  -Xlinker -export-dynamic -Wl,-O1 -Wl,-Bsymbolic-functions

# 添加动态库的位置
LINK_DIRECTORIES("/usr/lib/python3.6/config-3.6m-x86_64-linux-gnu")

add_executable(c_python src/c_python.cpp)
target_link_libraries(c_python -lpython3.6m)

c_python.cpp

//
// Created by daybeha on 2022/7/7.
//

#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <iostream>

using namespace std;


int main(int argc, char *argv[])
{


    Py_SetProgramName(reinterpret_cast<wchar_t *>(argv[0]));

//    wchar_t *program = Py_DecodeLocale(argv[0], NULL);
//    if (program == NULL) {
//        fprintf(stderr, "Fatal error: cannot decode argv[0]\n");
//        exit(1);
//    }
//    Py_SetProgramName(program);  /* optional but recommended */
//    Py_Initialize();
//    PyRun_SimpleString("from time import time,ctime\n"
//                       "print('Today is', ctime(time()))\n");
//    if (Py_FinalizeEx() < 0) {
//        exit(120);
//    }
//    PyMem_RawFree(program);
//    return 0;
//


    PyObject *pName, *pModule, *pFunc;
    PyObject *pArgs, *pValue;
    int i;

    if (argc < 3) {
        fprintf(stderr,"Usage: call pythonfile funcname [args]\n");
        return 1;
    }

    Py_Initialize();
//    PyRun_SimpleString("#!/usr/include/python3\n");
    PyRun_SimpleString("print ('Hello Python!')\n");
    PyRun_SimpleString("from time import time,ctime\n"
                       "print('Today is', ctime(time()))\n");

    PyRun_SimpleString("import platform\n"
                       "print(f\"Python Version: {platform.python_version()}\")\n");


    // 将Python工作路径切换到待调用模块所在目录,一定要保证路径名的正确性
    string path = "/home/daybeha/Documents/ROS_proj/test/src/time_acquire/scripts";
    string chdir_cmd = string("sys.path.append(\"") + path + "\")";
//    const char* cstr_cmd = chdir_cmd.c_str();
    PyRun_SimpleString("import sys");
    PyRun_SimpleString(chdir_cmd.c_str());
    PyRun_SimpleString("print(sys.path)");


    // agrv[1] 为 python脚本
    pName = PyUnicode_DecodeFSDefault(argv[1]);


    /* Error checking of pName left out */
    pModule = PyImport_Import(pName);
    Py_DECREF(pName);

    if (pModule != NULL) {
        // argv[2] 为 指定的函数
        pFunc = PyObject_GetAttrString(pModule, argv[2]);
//        pFunc = PyObject_GetAttrString(pModule, "great_func");

        /* pFunc is a new reference */
        if (pFunc && PyCallable_Check(pFunc)) {
            pArgs = PyTuple_New(argc - 3);
            for (i = 0; i < argc - 3; ++i) {
                pValue = PyLong_FromLong(atoi(argv[i + 3]));
                if (!pValue) {
                    Py_DECREF(pArgs);
                    Py_DECREF(pModule);
                    fprintf(stderr, "Cannot convert argument\n");
                    return 1;
                }
                /* pValue reference stolen here: */
                PyTuple_SetItem(pArgs, i, pValue);
            }
            pValue = PyObject_CallObject(pFunc, pArgs);
            Py_DECREF(pArgs);
            if (pValue != NULL) {
                printf("Result of call: %ld\n", PyLong_AsLong(pValue));
                Py_DECREF(pValue);
            }
            else {
                Py_DECREF(pFunc);
                Py_DECREF(pModule);
                PyErr_Print();
                fprintf(stderr,"Call failed\n");
                return 1;
            }
        }
        else {
            if (PyErr_Occurred())
                PyErr_Print();
            fprintf(stderr, "Cannot find function \"%s\"\n", argv[2]);
        }
        Py_XDECREF(pFunc);
        Py_DECREF(pModule);
    }
    else {
        PyErr_Print();
        fprintf(stderr, "Failed to load \"%s\"\n", argv[1]);
        return 1;
    }

    if (Py_FinalizeEx() < 0) {
        return 120;
    }
    return 0;

}

c_py_test.py

def great_func(a):
    return a + 1
    
# # # 查看python 版本
# import platform
# print(platform.python_version())

注:Python文件最好不要命名为test,可能会有冲突

运行

./c_python c_py_test great_func 3

在这里插入图片描述

Gcc

如果上面cmake编译不通,可以试试gcc版本:

gcc c_python.cpp -o c_python -I/usr/include/python3.6m -lpython3.6m

执行

./c_python  c_py_test great_func 9

在这里插入图片描述

若遇到类似报错:
在这里插入图片描述
需要:

export PYTHONPATH=.:/usr/include/python3.6:$PYTHONPATH

Reference

如何实现 C/C++ 与 Python 的通信?
Python.h的Cmake配置
python文档 – 拓展和嵌入
python文档 – python/C API接口
上面文档的中译版
cmake的项目c++调用python方法-爱代码爱编程

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

昼行plus

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

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

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

打赏作者

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

抵扣说明:

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

余额充值