目录
现在很多产品和技术的方向开始偏向智能化,数据化。所以为了能达到对应要求,很多时候python的对应API是非常好用的。但开发又不得不使用C,为了兼容,我们有时不得不使用C来调用Python。
有参和无参的不同只有两个,第一是要构建参数,第二是要解析返回值。
现在很多产品和技术的方向开始偏向智能化,数据化。所以为了能达到对应要求,很多时候python的对应API是非常好用的。但开发又不得不使用C,为了兼容,我们有时不得不使用C来调用Python。
1.下载对应依赖库:
sudo apt install libpython3.10-dev
2.构建模块:
这里为了完整学习整个过程,所以采用自定义模块而不是调用内置模块:
def HelloWorld():
print("hello world")
由于调用函数分有参和无参,所以这里再配一个:
def Test(agrv)
print("the argv is:",argv)
return 1
3.无参调用程序编写:
再写程序之前,我们要熟悉整个流程:
1.初始化Python编辑器
2.更改内置环境变量,使得Python编辑器可以搜索到自定义模块
3.调用对应模块
4..调用对应模块中的函数对象,本质上是获取一个函数指针
5.调用函数
6.释放所有使用的Python对象并关闭Python编辑器
然后我们要熟悉一些基本的API:
PyObject *PyImport_ImportModule(const char *name):传入模块名称,系统会检索sys.path中所有路径来找该模块,返回模块的引用。
PyObject *PyObject_GetAttrString(PyObject *o, const char *attr_name):传入一个引用和对象名称,系统会根据引用所指向的目标找到它对应的对象并返回它的引用。
PyObject *PyObject_CallObject(PyObject *callable, PyObject *args):传入一个引用,这里适用于传入函数对象的引用。第二个参数是对应函数所需要的参数。系统将调用对应函数。
void Py_DECREF(PyObject *o) :释放对象。
void Py_Initialize():初始化Python解释器 void Py_Finalize():关闭Python解释器。
Finally,我们开始写代码吧:
#include Python.h
int main(){
Py_Initialize();
PyObject *sys = PyImport_ImportModule(sys) //找到sys模块,并返回它的引用
PyObject *path = PyObject_GetAttrString(sys,path) //找到sys.path
//将当前目录添加到path中,准确来说这里是要把你自定义的模块对应的路径添加进去
PyList_Append(sys, PyUnicode_FromString("."))
PyObject *file = PyImport_ImportModule(HelloWorld) //获取对应模块
PyObject *Hello= PyObject_GetAttrString(file,Hellworld) //找到函数对象
PyObject *call = PyObject_CallObject(Hello, NULL) //调用函数
Py_DECREF(file)
Py_DECREF(Hello)
Py_DECREF(call)
Py_Finalize()
return 0;
}
4.有参调用程序编写
有参和无参的不同只有两个,第一是要构建参数,第二是要解析返回值。
这里要了解两个新的API:
PyObject *Py_BuildValue(const char *format, ...):构建参数,匹配规则如下
在fomat传入对于值即可。
int PyArg_Parse(PyObject *args, const char *format, ...):解析返回值。
其余步骤和上述的完全一致:
#include Python.h
int main(){
Py_Initialize();
PyObject *sys = PyImport_ImportModule(sys) //找到sys模块,并返回它的引用
PyObject *path = PyObject_GetAttrString(sys,"path") //找到sys.path
//将当前目录添加到path中,准确来说这里是要把你自定义的模块对应的路径添加进去
PyList_Append(sys, PyUnicode_FromString("."))
PyObject *file = PyImport_ImportModule(Test) //获取对应模块
PyObject *Testfunc = PyObject_GetAttrString(file,"Test") //找到函数对象
PyObject *para = Py_BuildValue("i",1234)
PyObject *call = PyObject_CallObject(Testfunc , para) //调用函数
int result;
PyArg_Parse(para, "s", &result);
printf("%d",resualt);
Py_DECREF(file)
Py_DECREF(Testfunc )
Py_DECREF(para)
Py_DECREF(call)
Py_Finalize()
return 0;
}
这样就完成基本的有参和无参的C调PythonAPI了。