Cython的函数

1 函数定义:

1.1 在Cython里定义一个类C函数:

1.1.1 在这里之所以说是定义一个"类C”函数,而不是一个C函数,是因为它和纯C函数的定义还是有区别的,具体看下面的例子:

1.1.2 例1:

cdef int Max(int a,int b):

if a>b:

return a

else:

return b

可见,定义一个C函数和纯C还是比较相似的

但是语法却是遵循python的语法

1.1.3 再来看成一个比较怪异的例子,例2:

cdef Max(int a,b):

if a>b:

return a

else:

return b

这个例子就有点怪了,牛不是牛,马不像马,还是从翻译出来的c代码中去找答案吧:

先创建一个test.pyx

cdef Max(int a,b):

if a>b:

return a

else:

return b

再转成C代码:

cython -o test.c test.pyx

打开test.c,搜索cdef Max定义到下面的代码:

/* "test.pyx":1

* cdef Max(int a,b):            #<<<<<<<<<<<<<<

*     if a>b:

*         return a

*/

static PyObject *__pyx_f_4test_Max(int __pyx_v_a, PyObject *__pyx_v_b) {

...

总结一下:

如果一个函数的参数或者返回值没有指定类型,那么它就是一个python对象,在进行操作时会将python对象转换成相应的C类型

如果参数或者返回值指定了类型,那么不会进行任何转换

1.1.4 再来看一个例子,例3

cdef object Max(int a,object b):

if a>b:

return a

else:

return b

和上一个例子不同的地方就是加了object关键,这表明这是一个python对象

它其实和上面生成的C代码是一样的,

这也验证了上面那个例子的理解是正确的

1.1.5 一个问题,如何在C代码里调用Cython里定义的C函数呢?

有时候,我们不仅仅是需要在Python代码里调用C代码,还有可能需要在Cython之外中的C代码里里调用Python的代码,

而我们知道,在Cython里定义的C函数是可以直接调用Python代码的

这样,可以通过在Cython外的C函数里调用Cython里定义的C函数来达到在C代码里调用Python代码的目的

但是,从上面的例子来看,经过Cython的翻译之后,函数名称被改变了,并且函数是static的,对外不可见,是不是无法调用?

答案很否定的,只要将Cython中定义的C函数声明为public或者extern即可,具体的来例子:

cdef public int Max(int a,int b):

if a>b:

return a

else:

return b

用Cython翻译成C代码后:

* cdef public int Max(int a,int b):            #<<<<<<<<<<<<<<

*     if a>b:

*         return a

*/

int Max(int __pyx_v_a,int __pyx_v_b) {

...

这样,这个函数就可以另外的C代码中补调用了。

但是,调用是可以调用,但是如果这个C函数里又调用了Python代码的话,在C代码里直接调用这个函数,程序会崩溃,这个另外的篇幅中再详细的讨论。

1.2  在Cython里定义一个类Python函数:

1.2.1 和类C函数的定义相似,只是以def开头,而不是以cdef开头

1.2.2 不同的地方是不能指定返回值的类型,这个很好理解,Python的函数肯定返回的是一个Python对象了,不可能返回一个C类型

1.2.3 即使你在Python里没有调用return,或者没有return一个对象,Python也默认会返回一个None对象

2 让类C函数在出错时抛出异常

2.1 这里有两种出错的情况

2.1.1 一种是C函数返回一个错误值

2.1.2 另外一种情况就是C函数里调用的Python代码出现的异常

2.2 首先来看一个例子:

cdef int ExceptTest(int n):

a = "abc"

print a.length()

return n

def CallExceptTest(intn):

return ExceptTest(n)

2.2.1 这里故意调用了一个字符串对象不存在的方法length

Subtopic

2.2.2 运行例子:

>>> import test

>>> test.CallExceptTest(-1)

Exception AttributeError: "'str'object has no attribute 'length'" in 'test.ExceptTest' ignored

0

2.2.3 可见错误被忽略了

2.3 如何让C函数抛出异常呢?还是先看例子:

import traceback

import sys

cdef int ExceptTest() except -1:

a = "abc"

print a.length()

return 1

def CallExceptTest():

try:

ExceptTest()

except Exception:

print "Exceptionin user code:"

traceback.print_exc(file=sys.stdout)

2.3.1 这个例子比上个例子在函数的声明时加上了 except -1

2.3.2 意思是异常产生时返回-1

2.3.3 测试一下:

>>> import test;test.CallExceptTest()

Exception in user code:

Traceback (most recent call last):

File "test.pyx", line 14,in test.CallExceptTest (test.c:809)

ExceptTest()

File "test.pyx", line 9,in test.ExceptTest (test.c:718)

print a.length()

AttributeError: 'str' object has noattribute 'length'

>>>

可见,这可比上个例子中只打印只一句冷冰冰的ignore好多了

通过异常时打出来的堆栈信息,可以定位到具体在test.pyx的哪一行出的错

这是不是比没有延时异常时好多了?

2.4 再来看下如果不是在C函数中调用的Python中出错会怎样:

import traceback

import sys

cdef int ExceptTest() except -1:

return -1

def CallExceptTest():

try:

ExceptTest()

except Exception:

print "Exceptionin user code:"

traceback.print_exc(file=sys.stdout)

2.4.1 这个例子中直接返了了-1

2.4.2 测试一下:

>>> importtest;test.CallExceptTest()

Traceback (most recent call last):

File "<stdin>", line1, in <module>

SystemError: errorreturn without exception set

2.4.3 直接抛出了一个SystemError,也没有堆栈信息输出

2.5 问题:有没有办法只要想在C函数中调用Python代码出错时抛出异常呢

2.5.1 答案当然是肯定的,在编程的世界里,永远都是只有想不到的,没有做不到的,

2.5.2 只要将except -1改成except? -1即可,

2.5.3 这样Cython就会在函数返回-1时调用PyErr_Occurred()来判断是否真的有一个异常产生,从而避免上个例子中出现的情况。

2.6 如果函数是void型,没有返回值,怎么让函数返回异常?

2.6.1 很简单,用except* 即可

如 cdef void Test() except* :

Cython基础--Cython的函数相关推荐

  1. Cython基础--Cython的类型

    Cython的类型 1 类型定义 1.1 定义一个C变量: 1.1.1 在Cython里定义一个C变量和C语言类似,不同的地方就是在声明的最前面要加上cdef,另外,末尾不用加分号";&qu ...

  2. openresty开发系列14--lua基础语法3函数

    openresty开发系列14--lua基础语法3函数 一)function (函数) 有名函数: optional_function_scope function function_name( ar ...

  3. 【Python基础】Python 函数使用总结

    我的施工之路 目前已完成,以下五期Python专题总结: 1我的施工计划 2数字专题 3字符串专题 4列表专题 5流程控制专题 6编程风格专题 今天是Python函数专题,目录结构: Python 函 ...

  4. Python基础day05【函数应用:学生管理系统、拆包、今日总结】

    视频.源码.课件.软件.笔记:超全面Python基础入门教程[十天课程]博客笔记汇总表[黑马程序员] Python基础day05[函数(函数传参的两种形式.函数形参).拆包.引用.可变与不可变类型.引 ...

  5. Python基础day05【函数(局部变量、全局变量、多函数执行流程、函数返回值、函数参数)、拆包、引用、可变与不可变类型、函数注意事项】

    视频.源码.课件.软件.笔记:超全面Python基础入门教程[十天课程]博客笔记汇总表[黑马程序员] Python基础day05[函数(函数传参的两种形式.函数形参).拆包.引用.可变与不可变类型.引 ...

  6. [C/C++基础知识] main函数的参数argc和argv

    该篇文章主要是关于C++\C语言最基础的main函数的参数知识,是学习C++或C语言都必备的知识点.不知道你是否知道该知识?希望对大家有所帮助. 一.main()函数参数 通常我们在写主函数时都是vo ...

  7. IOS基础之绘图函数的使用

    IOS基础之绘图函数的使用 // // HMView.m // 25-绘图步骤 // // Created by 鲁军 on 2021/2/14. //#import "HMView.h&q ...

  8. python求最小值不能使用min和sotred_python基础——内置函数

    python基础--内置函数  一.内置函数(python3.x) 内置参数详解官方文档: https://docs.python.org/3/library/functions.html?highl ...

  9. python什么元素为真_如何使用Python基础内置函数

    如何使用Python基础内置函数 发布时间:2020-08-05 13:46:59

最新文章

  1. 一位群友作为后端开发在滴滴和头条分别干了 2 年的经验总结
  2. 【 Vivado 】打包属于自己的IP
  3. (23/24) webpack实战技巧:如何在webpack环境中使用Json
  4. Mysql到Redis的数据协议(可以按照写redis的协议,自测已经成功,key值可以自己变化,不一定非要是id)
  5. oracle database link创建
  6. uni-app目录结构介绍
  7. Cisco/华为 远程管理设备telnet的N种设置方法
  8. vf程序设计与c语言,周四的C语言和VF,这些你有了么?
  9. 技巧:使用User Control做HTML生成(转)
  10. 西门子plc程序好坏判定
  11. 25 岁的 Linux 已经无处不在,它是如何毁了微软统治世界的计划?
  12. 第五节:通信之WLAN(MAC地址)
  13. 使用while循环实现xyz+yzz=532
  14. 关于2018后新款 Mac增加T2安全芯片造成无法U盘启动解决办法
  15. OpenStack-Ironic裸金属简介
  16. Servlet概念性回顾(结合Ajax)
  17. 从零开始搭建创业公司全新技术栈
  18. 英伟达GTC 公告确认这是一个互联的多芯片世界
  19. mybatis动态sql及分页
  20. 外汇超短线交易中的“剥头皮”

热门文章

  1. 解决typora 或markdown文档图片失效问题
  2. 机房动环监控系统应用意义
  3. Java 从多线程到并发编程(五)—— 线程调度 优先级倒置(反转) 阻塞 死锁 suspend
  4. DOM4J解析XML文档
  5. 【转】FILE *fp fopen 参数
  6. Kafka生产者是如何发送消息的?
  7. k8s组件的梳理,Glide的缓存机制
  8. 那些年我用过的JSON格式化工具
  9. python中格式化输出的作用是什么_python格式化输出是什么意思
  10. VMware Tools (ubuntu系统)安装详细过程与使用