100字范文,内容丰富有趣,生活中的好帮手!
100字范文 > C语言调用Python脚本

C语言调用Python脚本

时间:2019-01-19 17:18:29

相关推荐

C语言调用Python脚本

目录

一、头文件

二、使用步骤

1.初始化python模块

2.设置python的搜索路径

3.导入python脚本

4.导入调用的方法

5.构建参数

6.调用方法

7.解析返回值

8.释放资源

三、程序示例

四、编译

一、头文件

#include <python3.6/Python.h>

或者使用其他版本的python也可以。

如若头文件不存在,请执行如下命令安装

apt-get install python3-dev

二、使用步骤

1.初始化python模块

void Py_Initialize();

初始化完成后,可以调用函数Py_IsInitialized()来判断初始化是否成功。

/*Return true (nonzero) when the Python interpreter has been initialized,false (zero) if not. */int Py_IsInitialized();

成功返回 true(非0值),失败返回 false(0)

使用完毕后需要使用对应的函数Py_Finalize()来释放python资源,一般来说Py_Initialize和Py_Finalize应该是成对出现的。

void Py_Finalize();/*This is a backwards-compatible version of Py_FinalizeEx() that disregards the return value.*/int Py_FinalizeEx();/*Part of the Stable ABI since version 3.6.Undo all initializations made by Py_Initialize() and subsequent use of Python/C API functions, and destroy all sub-interpreters (see Py_NewInterpreter() below) that were created and not yet destroyed since the last call to Py_Initialize(). Ideally, this frees all memory allocated by the Python interpreter. This is a no-op when called for a secondtime (without calling Py_Initialize() again first). Normally the return value is 0. If there were errors during finalization (flushing buffered data), -1 is returned.This function is provided for a number of reasons. An embedding application might want to restart Python without having to restart the application itself. An application that has loaded the Python interpreter from a dynamically loadable library (or DLL) might want to free all memory allocated by Python before unloading the DLL. During a hunt for memory leaks in an application a developer might want to free all memory allocated by Python before exiting from the application.Bugs and caveats: The destruction of modules and objects in modules is done in random order; this may cause destructors (__del__() methods) to fail when they depend on other objects (even functions) or modules. Dynamically loaded extension modules loaded by Python are not unloaded. Small amounts of memory allocated by the Python interpreter may not be freed (if you find a leak, please report it). Memory tied up in circular references between objects is not freed. Some memory allocated by extension modules maynot be freed. Some extensions may not work properly if their initialization routine is called more than once; this can happen if an application calls Py_Initialize() and Py_FinalizeEx() more than once.Raises an auditing event cpython._PySys_ClearAuditHooks with no arguments.*/

对于Py_Finalize(),是Py_FinalizeEx()的向后兼容版本,它会忽略返回值。Py_FinalizeEx()如上所示为官方文档解释的原话,主要作用就是释放资源。

2.设置python的搜索路径

//相当于在python中的import sys语句。这个函数相当于直接运行python语句PyRun_SimpleString("import sys");//是将搜索路径设置为当前目录。PyRun_SimpleString("sys.path.append('./')");

PyRun_SimpleString()这个函数相当于直接运行python语句,将搜索路径设置为你所调用的python脚本所在的路径,其目的是为了找到导入的python脚本,为下一步做准备。

3.导入python脚本

/*参数:name - 需要调用python脚本的名称(不包括.py)返回值:成功返回PyObject指针,失败返回NULL*/PyObject *PyImport_ImportModule(const char *name);

4.导入调用的方法

/*参数:pmodule - PyImport_ImportModule的返回值name - 函数名返回值:成功返回PyObject指针,失败返回NULL*/PyObject *PyObject_GetAttrString(PyObject *pmodule, const char *name);

5.构建参数

如果需要想python脚本传递参数的话需要构建参数,参数类型不定,可以是整型、浮点型、字符串,包括元组类型等都可以传入。一般会用到PyTuple_New,Py_BuildValue,PyTuple_SetItem等几个函数。

/*构建python参数*/PyObject *Py_BuildValue(const char *format, ...);

对于Py_BuildValue函数中format格式的说明如下:

在下面的描述中,圆括号 () 内的是格式单元将要返回的 Python 对象类型;方括号 [] 内的是传递的 C 变量(变量集)的类型。

字符例如空格,制表符,冒号和逗号在格式化字符串中会被忽略(但是不包括格式单元,如s#)。这可以使很长的格式化字符串具有更好的可读性。

s(strNone) [const char *]

使用'utf-8'编码将空终止的 C 字符串转换为 Pythonstr对象。如果 C 字符串指针为NULL,则使用None

s#(strNone) [const char *,Py_ssize_t]

使用'utf-8'编码将 C 字符串及其长度转换为 Pythonstr对象。如果 C 字符串指针为NULL,则长度将被忽略,并返回None

y(bytes) [const char *]

这将 C 字符串转换为 Pythonbytes对象。 如果 C 字符串指针为NULL,则返回None

y#(bytes) [const char *,Py_ssize_t]

这会将 C 字符串及其长度转换为一个 Python 对象。 如果该 C 字符串指针为NULL,则返回None

z(strorNone) [const char *]

s一样。

z#(strNone) [const char *,Py_ssize_t]

s#一样。

u(str) [const wchar_t *]

将空终止的wchar_t的 Unicode (UTF-16 或 UCS-4) 数据缓冲区转换为 Python Unicode 对象。 如果 Unicode 缓冲区指针为NULL,则返回None

u#(str) [const wchar_t *,Py_ssize_t]

将 Unicode (UTF-16 或 UCS-4) 数据缓冲区及其长度转换为 Python Unicode 对象。 如果 Unicode 缓冲区指针为NULL,则长度将被忽略,并返回None

U(strNone) [const char *]

s一样。

U#(strNone) [const char *,Py_ssize_t]

s#一样。

i(int) [int]

将一个 Cint整型转化成 Python 整型对象。

b(int) [char]

将一个 Cchar字符型转化成 Python 整型对象。

h(int) [short int]

将一个 Cshort int短整型转化成 Python 整型对象。

l(int) [long int]

将一个 Clong int长整型转化成 Python 整型对象。

B(int) [unsigned char]

将一个 Cunsigned char无符号字符型转化成 Python 整型对象。

H(int) [unsigned short int]

将一个 Cunsigned long无符号短整型转化成 Python 整型对象。

I(int) [unsigned int]

将一个 Cunsigned long无符号整型转化成 Python 整型对象。

k(int) [unsigned long]

将一个 Cunsigned long无符号长整型转化成 Python 整型对象。

L(int) [long long]

将一个 Clong long长长整形转化成 Python 整形对象。

K(int) [unsigned long long]

将一个 Cunsigned long long无符号长长整型转化成 Python 整型对象。

n(int) [Py_ssize_t]

将一个 CPy_ssize_t类型转化为 Python 整型。

c(bytes长度为1 ) [char]

将一个 Cint整型代表的字符转化为 Pythonbytes长度为 1 的字节对象。

C(str长度为 1) [int]

将一个 Cint整型代表的字符转化为 Pythonstr长度为 1 的字符串对象。

d(float) [double]

将一个 Cdouble双精度浮点数转化为 Python 浮点数类型数字。

f(float) [float]

将一个 Cfloat单精度浮点数转化为 Python 浮点数类型数字。

D(complex) [Py_complex *]

将一个 CPy_complex类型的结构转化为 Python 复数类型。

O(object) [PyObject *]

将 Python 对象传递不变(其引用计数除外,该计数由 1 递增)。 如果传入的对象是NULL指针,则假定这是由于生成参数的调用发现错误并设置异常而引起的。因此,Py_BuildValue()将返回NULL,但不会引发异常。 如果尚未引发异常,则设置SystemError

S(object) [PyObject *]

O相同。

N(object) [PyObject *]

O相同,然而它并不增加对象的引用计数。当通过调用参数列表中的对象构造器创建对象时很实用。

O&(object) [converter,anything]

通过converter函数将anything转换为 Python 对象。 该函数调用时会传入anything(应与void*兼容) 作为参数并且应当返回一个“新的”Python 对象,或者当发生错误时返回NULL

(items)(tuple) [matching-items]

将一个 C 变量序列转换成 Python 元组并保持相同的元素数量。

[items](list) [相关的元素]

将一个 C 变量序列转换成 Python 列表并保持相同的元素数量。

{items}(dict) [相关的元素]

将一个C变量序列转换成 Python 字典。每一对连续的 C 变量对作为一个元素插入字典中,分别作为关键字和值。

构建示例:

//构建一个整型参数PyObject *pArg = Py_BuildValue("i", 5);//构建两个参数一个整型,一个浮点型PyObject *pArg = Py_BuildValue("(i, f)", 5, 2.4);

/*构建元组参数:size - 元组的大小*/PyObject *PyTuple_New(Py_ssize_t size);

构建元组的函数很简单,参数为构建的元组的大小。但是构建完元组之后还需要构建元组中的每一位元素,构建完之后就需要用到如下函数。

/*说明:在 p 指向的元组的 pos 位置插入对对象 o 的引用参数:p - 这应该是一个元组pos - 元组中的位置0-no - 要插入元组p的对象返回值:成功时返回 0; 如果 pos 越界,则返回 -1,并抛出一个 IndexError 异常。*/int PyTuple_SetItem(PyObject *p, Py_ssize_t pos, PyObject *o);

构建示例:

PyObject *pInt = Py_BuildValue("i", 3); //构建整型PyObject *pFloat = Py_BuildValue("f", 2.1); //构建浮点型PyObject *pyTupleList = PyTuple_New(2); //创建大小为2的元组PyTuple_SetItem(pyTupleList, 0, pInt); //在第1个位置插入pIntPyTuple_SetItem(pyTupleList, 1, pFloat); //在第2个位置插入pFloat

6.调用方法

/*说明:调用方法,返回结果参数:callable_object - 方法,PyObject_GetAttrString返回的对象args - 传入的参数,可以为NULL返回值:成功时返回结果,在失败时抛出一个异常并返回 NULL*/PyObject *PyObject_CallObject(PyObject *callable_object, PyObject *args);//PyEval_CallObject在新版本中已被弃用

可以看到,这里的参数args只有一个,所以在传入多个参数时,可以构建元组传入。

7.解析返回值

/*说明:解析函数调用的返回值,并保存参数:args - PyObject_CallObject的返回返回值:成功返回true,失败返回false*/int PyArg_Parse(PyObject *args, const char *format, ...);/*说明:解析函数调用的返回值,并保存(可解析元组,多个参数)参数:args - PyObject_CallObject的返回返回值:成功返回true,失败返回false*/int PyArg_ParseTuple(PyObject *args, const char *format, ...);

PyArg_Parse()和PyArg_ParseTuple()的format与Py_BuildValue部分类似,说明如下:

字符串和缓存区

这些格式允许将对象按照连续的内存块形式进行访问。你没必要提供返回的 unicode 字符或者字节区的原始数据存储。

s(str) [const char *]

将一个 Unicode 对象转换成一个指向字符串的 C 指针。一个指针指向一个已经存在的字符串,这个字符串存储的是传如的字符指针变量。C 字符串是已空结束的。Python 字符串不能包含嵌入的无效的代码点;如果由,一个ValueError异常会被引发。Unicode 对象被转化成'utf-8'编码的 C 字符串。如果转换失败,一个UnicodeError异常被引发。

s*(strorbytes-like object) [Py_buffer]

这个表达式既接受 Unicode 对象也接受类字节类型对象。它为由调用者提供的Py_buffer结构赋值。这里结果的 C 字符串可能包含嵌入的 NUL 字节。Unicode 对象通过'utf-8'编码转化成 C 字符串。

s#(str, read-onlybytes-like object) [const char *,Py_ssize_t]

s*,除了它不接受易变的对象。结果存储在两个 C 变量中,第一个是指向 C 字符串的指针,第二个是它的长度。字符串可能包含嵌入的 null 字节。Unicode 对象都被通过'utf-8'编码转化成 C 字符串。

z(strorNone) [const char *]

s类似,但 Python 对象也可能为None,在这种情况下,C 指针设置为NULL

z*(str,bytes-like objectorNone) [Py_buffer]

s*类似,但 Python 对象也可能为None,在这种情况下,Py_buffer结构的buf成员设置为NULL

z#(str, read-onlybytes-like object或者None) [const char *,Py_ssize_t]

s#类似,但 Python 对象也可能为None,在这种情况下,C 指针设置为NULL

y(read-onlybytes-like object) [const char *]

这个表达式将一个类字节类型对象转化成一个指向字符串的 C 指针;它不接受 Unicode 对象。字节缓存区必须不包含嵌入的 null 字节;如果包含了 null 字节,会引发一个ValueError异常。

在 3.5 版更改:以前,当字节缓冲区中遇到了嵌入的 null 字节会引发TypeError

y*(bytes-like object) [Py_buffer]

s*的变式,不接受 Unicode 对象,只接受类字节类型变量。这是接受二进制数据的推荐方法。

y#(read-onlybytes-like object) [const char *,Py_ssize_t]

s#的变式,不接受 Unicode 对象,只接受类字节类型变量。

S(bytes) [PyBytesObject *]

要求 Python 对象为bytes对象,不尝试进行任何转换。 如果该对象不为 bytes 对象则会引发TypeError。 C 变量也可被声明为PyObject*类型。

Y(bytearray) [PyByteArrayObject *]

要求 Python 对象为bytearray对象,不尝试进行任何转换。 如果该对象不为bytearray对象则会引发TypeError。 C 变量也可被声明为PyObject*类型。

u(str) [const Py_UNICODE *]

将一个 Python Unicode 对象转化成指向一个以空终止的 Unicode 字符缓冲区的指针。你必须传入一个Py_UNICODE指针变量的地址,存储了一个指向已经存在的 Unicode 缓冲区的指针。请注意一个Py_UNICODE类型的字符宽度取决于编译选项(16 位或者 32 位)。Python 字符串必须不能包含嵌入的 null 代码点;如果有,引发一个ValueError异常。

在 3.5 版更改:以前,当 Python 字符串中遇到了嵌入的 null 代码点会引发TypeError

Deprecated since version 3.3, will be removed in version 3.12:这是旧版样式Py_UNICODEAPI; 请迁移至PyUnicode_AsWideCharString().

u#(str) [const Py_UNICODE *,Py_ssize_t]

u的变式,存储两个 C 变量,第一个指针指向一个 Unicode 数据缓存区,第二个是它的长度。它允许 null 代码点。

Deprecated since version 3.3, will be removed in version 3.12:这是旧版样式Py_UNICODEAPI; 请迁移至PyUnicode_AsWideCharString().

Z(strNone) [const Py_UNICODE *]

u类似,但 Python 对象也可能为None,在这种情况下Py_UNICODE指针设置为NULL

Deprecated since version 3.3, will be removed in version 3.12:这是旧版样式Py_UNICODEAPI; 请迁移至PyUnicode_AsWideCharString().

Z#(strNone) [const Py_UNICODE *,Py_ssize_t]

u#类似,但 Python 对象也可能为None,在这种情况下Py_UNICODE指针设置为NULL

Deprecated since version 3.3, will be removed in version 3.12:这是旧版样式Py_UNICODEAPI; 请迁移至PyUnicode_AsWideCharString().

U(str) [PyObject *]

要求 Python 对象为 Unicode 对象,不尝试进行任何转换。 如果该对象不为 Unicode 对象则会引发TypeError。 C 变量也可被声明为PyObject*。

w*(可读写bytes-like object) [Py_buffer]

这个表达式接受任何实现可读写缓存区接口的对象。它为调用者提供的Py_buffer结构赋值。缓冲区可能存在嵌入的 null 字节。当缓冲区使用完后调用者需要调用PyBuffer_Release()

es(str) [const char *encoding, char **buffer]

s的变式,它将编码后的 Unicode 字符存入字符缓冲区。它只处理没有嵌 NUL 字节的已编码数据。

此格式需要两个参数。 第一个仅用作输入,并且必须为constchar*,它指向一个以 NUL 结束的字符串表示的编码格式名称,或者为NULL,这表示使用'utf-8'编码格式。 如果为 Python 无法识别的编码格式名称则会引发异常。 第二个参数必须为char**;它所引用的指针值将被设为带有参数文本内容的缓冲区。 文本将以第一个参数所指定的编码格式进行编码。

PyArg_ParseTuple()会分配一个足够大小的缓冲区,将编码后的数据拷贝进这个缓冲区并且设置*buffer引用这个新分配的内存空间。调用者有责任在使用后调用PyMem_Free()去释放已经分配的缓冲区。

et(str,bytesorbytearray) [const char *encoding, char **buffer]

es相同,除了不用重编码传入的字符串对象。相反,它假设传入的参数是编码后的字符串类型。

es#(str) [const char *encoding, char **buffer,Py_ssize_t*buffer_length]

s#的变式,它将已编码的 Unicode 字符存入字符缓冲区。不像es表达式,它允许传入的数据包含 NUL 字符。

它需要三个参数。 第一个仅用作输入,并且必须为constchar*,它指向一个编码格式名称,形式为以 NUL 结束的字符串或NULL,在后一种情况下将使用'utf-8'编码格式。 如果编码格式名称无法被 Python 识别则会引发异常。 第二个参数必须为char**;它所引用的指针值将被设为带有参数文本内容的缓冲区。 文本将以第一个参数所指定的编码格式进行编码。 第三个参数必须为指向一个整数的指针;被引用的整数将被设为输出缓冲区中的字节数。

有两种操作方式:

如果*buffer指向NULL指针,则函数将分配所需大小的缓冲区,将编码的数据复制到此缓冲区,并设置*buffer以引用新分配的存储。 呼叫者负责调用PyMem_Free()以在使用后释放分配的缓冲区。

如果*buffer指向非NULL指针(已分配的缓冲区),则PyArg_ParseTuple()将使用此位置作为缓冲区,并将*buffer_length的初始值解释为缓冲区大小。 然后,它将将编码的数据复制到缓冲区,并终止它。 如果缓冲区不够大,将设置一个ValueError

在这两个例子中,*buffer_length被设置为编码后结尾不为 NUL 的数据的长度。

et#(str,bytesbytearray) [const char *encoding, char **buffer,Py_ssize_t*buffer_length]

es#相同,除了不用重编码传入的字符串对象。相反,它假设传入的参数是编码后的字符串类型。

数字

b(int) [unsigned char]

将一个非负的 Python 整型转化成一个无符号的微整型,存储在一个 Cunsigned char类型中。

B(int) [unsigned char]

将一个 Python 整型转化成一个微整型并不检查溢出问题,存储在一个 Cunsigned char类型中。

h(int) [short int]

将一个 Python 整型转化成一个 Cshort int短整型。

H(int) [unsigned short int]

将一个 Python 整型转化成一个 Cunsigned short int无符号短整型,并不检查溢出问题。

i(int) [int]

将一个 Python 整型转化成一个 Cint整型。

I(int) [unsigned int]

将一个 Python 整型转化成一个 Cunsigned int无符号整型,并不检查溢出问题。

l(int) [long int]

将一个 Python 整型转化成一个 Clong int长整型。

k(int) [unsigned long]

将一个Python整型转化成一个Cunsigned long int无符号长整型,并不检查溢出问题。

L(int) [long long]

将一个 Python 整型转化成一个 Clong long长长整型。

K(int) [unsigned long long]

将一个 Python 整型转化成一个 Cunsigned long long无符号长长整型,并不检查溢出问题。

n(int) [Py_ssize_t]

将一个 Python 整型转化成一个 CPy_ssize_tPython 元大小类型。

c(bytes或者bytearray长度为 1) [char]

将一个 Python 字节类型,如一个长度为 1 的bytes或者bytearray对象,转化成一个 Cchar字符类型。

在 3.3 版更改:允许bytearray类型的对象。

C(str长度为 1) [int]

将一个 Python 字符,如一个长度为 1 的str字符串对象,转化成一个 Cint整型类型。

f(float) [float]

将一个 Python 浮点数转化成一个 Cfloat浮点数。

d(float) [double]

将一个Python浮点数转化成一个Cdouble双精度浮点数。

D(complex) [Py_complex]

将一个 Python 复数类型转化成一个 CPy_complexPython 复数类型。

其他对象

O(object) [PyObject *]

将 Python 对象(不进行任何转换)存储在 C 对象指针中。 因此,C 程序接收已传递的实际对象。 对象的引用计数不会增加。 存储的指针不是NULL

O!(object) [typeobject, PyObject *]

将一个 Python 对象存入一个 C 对象指针。 这类似于O,但是接受两个 C 参数:第一个是 Python 类型对象的地址,第二个是存储对象指针的 C 变量 (类型为PyObject*) 的地址。 如果 Python 对象不具有所要求的类型,则会引发TypeError

O&(object) [converter,anything]

通过一个converter函数将一个 Python 对象转换为一个 C 变量。 此函数接受两个参数:第一个是函数,第二个是 C 变量 (类型任意) 的地址,转换为void*类型。converter函数将以如下方式被调用:

status = converter(object, address);

其中object是待转换的 Python 对象而address为传给PyArg_Parse*函数的void*参数。 返回的status应当以1代表转换成功而以0代表转换失败。 当转换失败时,converter函数应当引发异常并且会让address的内容保持未修改状态。

如果converter返回Py_CLEANUP_SUPPORTED,则如果参数解析最终失败,它可能会再次调用该函数,从而使转换器有机会释放已分配的任何内存。在第二个调用中,object参数将为NULL;因此,该参数将为NULL;因此,该参数将为NULL,因此,该参数将为NULL``(如果值)为``NULLaddress的值与原始呼叫中的值相同。

在 3.1 版更改:Py_CLEANUP_SUPPORTED被添加。

p(bool) [int]

测试传入的值是否为真(一个布尔判断)并且将结果转化为相对应的 C true/false 整型值。如果表达式为真置1,假则置0。它接受任何合法的 Python 值。参见逻辑值检测获取更多关于 Python 如何测试值为真的信息。

3.3 新版功能.

(items)(tuple) [matching-items]

对象必须是 Python 序列,它的长度是items中格式单元的数量。C 参数必须对应items中每一个独立的格式单元。序列中的格式单元可能有嵌套。

传递 "long" 整型(整型的值超过了平台的LONG_MAX限制)是可能的,然而没有进行适当的范围检测——当接收字段太小而接收不到值时,最重要的位被静默地截断(实际上,C 语言会在语义继承的基础上强制类型转换——期望的值可能会发生变化)。

格式化字符串中还有一些其他的字符具有特殊的涵义。这些可能并不嵌套在圆括号中。它们是:

|

表明在 Python 参数列表中剩下的参数都是可选的。C 变量对应的可选参数需要初始化为默认值——当一个可选参数没有指定时,PyArg_ParseTuple()不能访问相应的 C 变量(变量集)的内容。

$

PyArg_ParseTupleAndKeywords()only:表明在 Python 参数列表中剩下的参数都是强制关键字参数。当前,所有强制关键字参数都必须也是可选参数,所以格式化字符串中|必须一直在$前面。

3.3 新版功能.

:

格式单元的列表结束标志;冒号后的字符串被用来作为错误消息中的函数名(PyArg_ParseTuple()函数引发的“关联值”异常)。

;

格式单元的列表结束标志;分号后的字符串被用来作为错误消息取代默认的错误消息。:;相互排斥。

解析示例:

//单个参数解析 a = 1PyArg_Parse(result, "i", &a);//单个参数解析 f('strings')PyArg_ParseTuple(args, "s", &s);//多个参数解析: f(1, 2,'strings')PyArg_ParseTuple(args, "lls", &k, &l, &s);//组合参数解析:元组+字符串+字符串长度: f((1, 2), 'strings')PyArg_ParseTuple(args, "(ii)s#", &i, &j, &s, &size);//可选参数解析:f('strings')// or f('strings', 'hello') // or f('strings', 'hello', 100000)PyArg_ParseTuple(args, "s|si", &file, &mode, &bufsize);

8.释放资源

/*说明:这是一个宏定义,释放PyObject*对象Py_DECREF:比Py_XDECREF较快Py_XDECREF:比Py_DECREF较为安全,需要判断PyObject是否为空再去释放*/Py_DECREF(PyObject*);Py_XDECREF(PyObject*);/*最后调用,与Py_Initialize对应*/Py_Finalize();

注:

当使用PyTuple_SetItem(PyObject *p, Py_ssize_t pos, PyObject *o)函数,将对象o插入对象p时,即在组装元组时,只需释放最外层的元组即可,且推荐使用Py_XDECREF更安全。

三、程序示例

C语言部分

#include <python3.6/Python.h>int main(){Py_Initialize(); //初始化if (!Py_IsInitialized()){return -1; //init python failed}//相当于在python中的import sys语句。这个函数是宏,相当于直接运行python语句PyRun_SimpleString("import sys");PyRun_SimpleString("sys.path.append('./')");//是将搜索路径设置为当前目录。PyObject *pmodule = PyImport_ImportModule("hello"); //导入hello.pyif (!pmodule){printf("cannot find hello.py\n");return -1;}else{printf("PyImport_ImportModule success\n");}PyObject *pfunc = PyObject_GetAttrString(pmodule, "func1"); //导入func1函数if (!pfunc){printf("cannot find func\n");Py_XDECREF(pmodule);return -1;}else{printf("PyObject_GetAttrString success\n");}// 向Python传参数是以元组(tuple)的方式传过去的,// 因此我们实际上就是构造一个合适的Python元组就可以了// 要用到PyTuple_New,Py_BuildValue,PyTuple_SetItem等几个函数/*这个元组其实只是传参的载体创建几个元素python函数就是几个参数,这里创建的元组是作为1个参数传递的*/PyObject *pArgs = PyTuple_New(3);PyObject *pVender = Py_BuildValue("i", 2);//构建参数1PyObject *pDataID = Py_BuildValue("i", 10001); //构建参数2PyObject *pyTupleList = PyTuple_New(2); //构建参数3,这里创建的元组是作为c的数组float arr_f[2];arr_f[0] = 78;arr_f[1] = 3.41;for (int i = 0; i < 2; i++){//这里是把c数组构建成python的元组PyTuple_SetItem(pyTupleList, i, Py_BuildValue("f", arr_f[i])); }//参数入栈PyTuple_SetItem(pArgs, 0, pVender);PyTuple_SetItem(pArgs, 1, pDataID);PyTuple_SetItem(pArgs, 2, pyTupleList);//调用python脚本函数PyObject *pResult = PyObject_CallObject(pfunc, pArgs);int a;float b;// PyArg_Parse(pResult, "i", &a);PyArg_ParseTuple(pResult,"if",&a,&b);printf("%d %f\n", a,b);//释放资源Py_XDECREF(pmodule);Py_XDECREF(pfunc);Py_XDECREF(pArgs);Py_XDECREF(pResult);Py_Finalize();return 0;}

python部分

import loggingLOG_FORMAT = "[%(asctime)s][%(levelname)s][%(module)s.py:%(lineno)d]---> %(message)s"DATE_FORMAT = "%Y%m%d %T"logging.basicConfig(filename="hello.log", level=logging.DEBUG, format=LOG_FORMAT, datefmt=DATE_FORMAT)ch = logging.StreamHandler() # 输出到控制台ch.setLevel(logging.DEBUG)ch.setFormatter(logging.Formatter(LOG_FORMAT,DATE_FORMAT))logging.getLogger().addHandler(ch)def func1(vender,dataid,tuple):logging.info("vender = %d, dataid = %d" % (vender,dataid))logging.info("type tuple = [%s] tuple = [%s]" % (str(type(tuple)), str(tuple)))return (15,5.6)

四、编译

gcc main.c -L/usr/lib/aarch64-linux-gnu -lpython3.6m -o main

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。