系统: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方法-爱代码爱编程