首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Python C Extensions - 为什么必须可调用的C函数接受参数并返回PyObject*

Python C Extensions - 为什么必须可调用的C函数接受参数并返回PyObject*

Python C Extensions 是一种允许将 C 语言扩展模块集成到 Python 程序中的方法。这些 C 语言扩展模块可以定义新的 C 函数,这些函数可以在 Python 代码中调用。这些 C 函数必须具有以下特点:

  1. 可调用的 C 函数:这些函数接受参数,并返回一个 PyObject * 类型的数据。这个返回类型表明该函数处理的结果将作为 Python 对象,而不是 C 语言的指针。
  2. 函数指针:这些 C 函数是函数指针,可以在 Python 代码中调用。这意味着可以在 Python 程序中创建一个指向 C 函数的指针,以便在需要时调用该函数。
  3. 包含类型信息:为了在 Python 中使用 C 函数,必须将函数的类型信息包含在扩展模块中。这可以通过在函数声明中添加类型注释来完成。

以下是一个简单的 Python C Extensions 示例,定义了一个名为 add 的 C 函数,用于将两个 PyObject * 指针相加并返回结果:

代码语言:c
复制
#include <Python.h>

static PyObject* add(PyObject* self, PyObject* args) {
    PyObject* a = NULL, * b = NULL;
    PyObject* result = NULL;

    if (PyArg_ParseTuple(args, "OO", &a, &b)) {
        result = PyNumber_Add(a, b);
        Py_DECREF(a);
        Py_DECREF(b);
    }

    return result;
}

static PyMethodDef AddMethods[] = {
    {"add", add, METH_VARARGS, "Add two numbers."},
    {NULL, NULL, 0, NULL} // Sentinel
};

PyMODINIT_FUNC init_addition(void) {
    Py_InitModule("addition", AddMethods);
}

将以上代码保存为 addition.c,然后将其编译为动态链接库 addition.so。接下来,在 Python 程序中导入 addition 模块,并使用 add 函数:

代码语言:python
代码运行次数:0
复制
import addition

result = addition.add(1, 2)
print(result)  # 输出 3

以上示例展示了如何创建一个 Python C Extensions,并展示了一个 C 函数如何接受参数并返回 PyObject * 类型的数据。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

CC++与Python双剑合璧

类型值转为C语言识别的int类型值 // "i"表示pythonC/C++之间int转换,其他转换参见本程序代码后面的表格 // PyArg_ParseTuple为可变参函数...= PyObject_GetAttrString(pModule, "mul"); // 将参数压栈 // 函数调用参数传递均是以元组形式打包, 这里2表示参数个数为2...PyObject *pArgs = PyTuple_New(2); // 0表示元组0下标,表示第一个参数, // Py_BuildValue用来将c/c++识别的类型转为python...识别的, // Py_BuildValue第一个参数为转换格式代码,第二个参数为传递给python函数参数 PyTuple_SetItem(pArgs, 0, Py_BuildValue...")); // 调用函数接收返回PyObject *pReturn = PyEval_CallObject(pFunc, pArgs); // 将python返回参数类型转为

86220

再探CC++扩展Python

函数功能是将Python对象C/C++类型数据,如果转换失败,返回0 第一个参数:包含从Python传递到C函数参数列表元组对象 第二个参数:是格式参数必须是字符串,已经预定义好了,零个或多个...一个格式单元描述一个Python对象。比如例子中‘i'表示将Python整数对象转换为纯C语言 int类型。 其余参数:其余参数必须是其类型由格式字符串确定变量地址,可以是多个地址。...这类似于“O”,但有两个C参数:第一个是Python类型对象地址,第二个是存储对象指针C变量(类型PyObject *)地址。如果Python对象没有必需类型,则会引发TypeError。...(只读字符缓冲区)→[char *,int] “w”:类似于“s”,但接受实现读写缓冲器接口任何对象。调用必须通过其他方式确定缓冲区长度,或者使用“w#”。...(读写字符缓冲区)→[char *,int] “items”:对象必须Python序列,其长度是项目中格式单位数。 C参数必须对应于各个格式单元initem。 可以嵌套序列格式单元。

67930

Python C API使用详解(一)

Py_IsInitialized()用于判断Python虚拟机初始化是否成功,True是成功,False是失败。 C/C++中调用Python之前必须先初始化虚拟机。...Py_BuildValue 可以使用其将C所有基本数据类型转换成Python访问数据类型。...O(object) [PyObject *] 不改变Python对象传递(引用计数除外,它增加1)。如果传入对象是NULL指针,则假定这是因为产生参数调用发现错误设置了异常。...S(object) [PyObject *] 与O相同 N((object) [PyObject *] 与O相同,但不会增加对象引用计数。通过调用参数列表中对象构造函数创建对象时很有用。...该函数调用任何东西(应与void *兼容)作为其参数返回“新”Python对象,如果发生错误则返回NULL。

5.7K21

工具丨用C语言扩展Python功能

PythonC语言扩展接口中,大部分函数都有一个或者多个参数PyObject指针类型,并且返回值也大都为PyObject指针。...参数args中包含了Python解释器要传递给C函数所有参数,通常使用PythonC语言扩展接口提供函数PyArg_ParseTuple()来获得这些参数值。...所有的导出函数返回一个PyObject指针,如果对应C函数没有真正返回值(即返回值类型为void),则应返回一个全局None对象(Py_None),并将其引用计数增1,如下所示: ?...Python解释器规定所有的初始化函数函数名都必须以init开头,加上模块名字。对于模块example来说,则相应初始化函数为: ?...当Python解释器需要导入该模块时,将根据该模块名称查找相应初始化函数,一旦找到则调用函数进行相应初始化工作,初始化函数则通过调用PythonC语言扩展接口所提供函数Py_InitModule

2.8K90

C++ 调用Python3

函数传入参数元组 获取返回值 根据Python函数定义解析返回值 初始化 在调用Python模块时需要首先包含Python.h头文件,这个头文件一般在安装Python目录中 include文件中...这个函数返回一个Python对象指针,在C++中表示为PyObject。...这里返回模块对象指针 然后调用 PyObject_GetAttrString 函数来加载对应Python模块中方法,这个函数需要两个参数,第一个是之前获取到对应模块指针,第二个参数函数名称...函数返回Python元组对象,这个元组就是Python函数返回值 获取到返回值之后就是解析参数了,我们可以使用对应函数Python元组转化为C++中变量 最后需要调用 Py_DECREF 来解除...解析元组 Python 函数返回是元组,在C++中需要进行对应解析,我们可以使用 PyTuple_GetItem 来获取元组中数据成员,这个函数返回PyObject 指针,之后再使用对应转化函数

2.2K50

PythonC:无缝集成,高效性能之道

通过使用Python扩展,我们可以借助其他编程语言优势,提升Python代码性能和功能。 为什么要使用C语言编写扩展?...如何编写Python扩展? 要编写Python扩展,我们需要完成以下几个步骤: 步骤1:定义扩展模块函数C语言中,我们需要声明实现Python扩展模块函数。...return Py_None; // 返回结果 } // Python包装器函数 static PyObject* py_module_function(PyObject* self, PyObject...* args) { // 解析Python参数 // ... // 调用C函数 // ... // 封装返回结果 // ......步骤4:使用Python扩展 完成编译后,我们可以在Python中使用刚刚编写C语言扩展。首先,需要将生成动态库文件导入到Python解释器环境中,然后就可以直接调用扩展模块中函数和方法了。

44520

Python 为什么能支持任意真值判断?

PyObject_IsTrue() 函数在计算过程中,依次会获取 nb_bool、mp_length 和 sq_length 值,对应应该就是 __bool__() 和 __len__() 这两个魔术方法返回值...另外,对于内置 bool(),它核心实现逻辑正是上面的 PyObject_IsTrue() 函数,源码如下(boolobject.c): ?...所以,Python 在对普通对象作真值判断时,并没有隐式地调用 bool(),相反它调用了一个独立函数PyObject_IsTrue()),而这个函数又被 bool() 所使用。...数字 文章小结 Python 中if xxx 这种简便写法,虽然是正规真值判断语法,它但并不符合常规语义。...在 C/C++/Java 之类语言中,要么 xxx 本身是布尔类型值,要么是一种返回布尔类型值操作,但是在 Python 中,这个“xxx”竟然还可以是任意 Python 对象!

1.1K20

Python一键转Jar包,Java调用Python新姿势!

官方介绍 Cython 是一个 Python 语言规范超集,它可以将 Python+C 混合编码.pyx 脚本转换为 C 代码,主要用于优化 Python 脚本性能或 Python 调用 C 函数库...注意2:这一类接口函数输入是一个 python str 类型字符串,输出亦然,如此便于移植以往通过JSON形式作为参数 RESTful 接口。...使用JSON好处是可以对参数进行封装,支持多种复杂参数形式,而不用重载出不同接口函数对外调用。...,封装了对原来Python中定义对JNI_API_testFuncion函数调用,同时要负责JNI层面的参数jstring类型转换。...登场时候了,它将会将所有pyx文件自动转换成.c文件,结合我们自己main.c文件,内部调用gcc生成一个动态二进制库文件。

3.8K11

Python: C扩展初体验

可以简单理解成就是 PythonC 对接函数,举个栗子: static PyObject *test(PyObject *self, PyObject *args){ int arg1,...C 用法用点不同了,特别是在函数形参那边PyObject self, PyObject args 第一个参数PyObject *self,这个参数Python内部使用,可以不用管; 第二个参数是...PyObject *args,这个参数非常重要,因为这个揽括了所有传给函数参数。...,函数 Py_BuildValue 会把所有的返回指都组装成 tuple 给 Python 相关官方文档:https://docs.python.org/2/c-a... 2....,这是有规定必须是 init + 模块名字,比方说,我最后编译出来文件是 test.so, 那我函数名就是 inittest, 这样在 Python 导入 test 模块时,才能找到这个函数调用

1.2K20

Android与Python混合编程

函数传一个参数 // 等价用法:py.getModule("hello").get("greet").call("Android"); py.getModule("hello...= "+sum.toString()); // 调用python函数,命名式传参,等同 sub(10,b=1,c=3) PyObject obj2 =...函数,将返回Pythonlist转为Javalist PyObject obj3 = py.getModule("hello").callAttr("get_list", 10,...没有方法重载,通常一个函数会声明很多参数,注意使用Kwarg类进行命名式传参 注意对象转换,PyObject类是桥梁,fromJava函数将一个Java对象转换为相应Python对象,toJava函数正好相反...中必须使用static_proxy方法进行包装,如需生成方法,还需要使用相关Python装饰器,详细用法见Static proxy文档[6] 静态代理同时配置多个 defaultConfig {

4.5K20

Python一键转Jar包 Java调用Python

官方介绍 Cython 是一个 Python 语言规范超集,它可以将 Python+C 混合编码.pyx 脚本转换为 C 代码,主要用于优化 Python 脚本性能或 Python 调用 C 函数库...注意2:这一类接口函数输入是一个 python str 类型字符串,输出亦然,如此便于移植以往通过JSON形式作为参数 RESTful 接口。...使用JSON好处是可以对参数进行封装,支持多种复杂参数形式,而不用重载出不同接口函数对外调用。...,封装了对原来Python中定义对JNI_API_testFuncion函数调用,同时要负责JNI层面的参数jstring类型转换。...登场时候了,它将会将所有pyx文件自动转换成.c文件,结合我们自己main.c文件,内部调用gcc生成一个动态二进制库文件。

1.7K40

Python源码剖析:深度探索Cpython对象-达观数据

Python 中创建一个对象,会分配内存并进行初始化,然后 Python 会用一个 PyObject * 来保存和维护这个对象,因此在 Python 中,变量传递(包括函数参数传递)实际上传递都是一个泛型指针...找到了之后将 a、b 作为参数传递进去,这会发生一次函数调用,会将对象维护值拿出来进行运算,然后根据相加结果创建一个新对象,再返回其对应 PyObject * 指针。...因为它们有哪些成员在底层都是写死Python 对它们了如指掌,因此可以通过 Python/C API 直接分配内存初始化。...但对于内置类型而言,我们推荐使用 Python/C API 创建,会直接解析为对应 C 一级数据结构,因为这些结构在底层都是已经实现好了,是可以直接用,无需通过诸如 list() 这种调用类型对象方式来创建...五、总结     Python是一门备受推崇脚本语言,以其简单语法和全面的功能而著称,快速实现各种业务。

25910

C语言武装Python,让代码执行速度飞起来

这个包裹函数接收一个 PyObject 类型指针(指向今后从 Python 代码传入参数)作为参数,再返回一个 PyObject 类型指针(指向上面函数返回值)给外部。...接着自然是调用 fastfactorial(n) 来计算阶乘,并用 Python 头文件里 Py_BuildValue 方法把返回值塞回 PyObject* 类型里。...最后一步,我们要添加一个函数python 代码导入这个模组时候执行这个函数。...当一个模组被 Python 代码导入时,这个方法就会被调用返回一个指向整个模组对象,包含了所有方法指针。...这个库文件可以被 Python 脚本调用执行我们用 C 编写阶乘函数。 05 测试结果 让我们试一下吧。

98920

深入理解Python虚拟机:super超级魔法背后原理

在Child类构造函数中,我们使用super().init(name)来调用父类Parent构造函数,以便在子类中初始化父类属性。...在Python中,每个类都有一个内置属性__mro__,它记录了方法解析顺序。MRO是根据C3线性化算法生成,它决定了在多重继承中调用方法顺序。...当对象进行方法调用时候,就会从类 mro 当中第一个类开始寻找,直到最后一个类为止,当第一次发现对应类有相应方法时就进行返回调用这个类这个方法。...为什么要进行这样处理呢,这是因为需要调用相应位置类父类方法,因此所有的使用 super 位置type都必须是所在类。...obj 绑定成一个方法对象返回,然后在进行方法调用时候就能够成功调用了。

16660

在Java中调用Python

因此能很好与JVM集成,比如利用JVM垃圾回收和JIT,直接导入调用JVM上其他语言编写库和函数。...IronPython将源码编译成TODO CLR,同样能很好与.NET平台集成。即与Jython相同,可以利用.NET框架JIT、垃圾回收等功能,能导入调用.NET上其他语言编写库和函数。...虽然我们理解了什么是Jython,但是还存在一个疑问,为什么Python语言存在这么多不同语言实现呢?为什么不能就只存在一个C语言实现版本就可以了呢?...=utf-8 print("Do simple thing in Python") print("输出中文") (3)在Java中单向调用Python程序中方法,需要传递参数接收返回值。....get(pythonObjName); // 调用python对象方法,传递参数接收返回PyObject result = pyObj.invoke("power", new PyObject

5K30
领券