ctypes给扩展模块中的函数传递回调函数

C语言中的回调函数

什么是回调函数我就不介绍了,我们先来看看C语言中如何使用回调函数。

函数指针

不过在看回调函数之前,我们先看看如何把一个函数赋值给一个变量。准确的说,是让一个指针指向一个函数,这个指针叫做函数指针。通常我们说的指针变量是指向一个整型、字符型或数组等变量,而函数指针是指向函数。函数指针可以像一般函数一样,用于调用函数、传递参数。

#include <stdio.h>

int add(int a, int b){
  int c;
  c = a + b;
  return c;
}

int main(int argc, char const *argv[]) {
  //创建一个指针变量p,让p等于指向add
  //我们看到就类似声明函数一样,指定返回值类型和变量类型即可
  //但是注意的是,中间一定是*p,不是p,因为这是一个函数指针,所以要有*
  int (*p)(int, int) = add;
  printf("1 + 3 = %d\n", p(1, 3)); //1 + 3 = 4
  return 0;
}

除此之外我们还以使用typedef

#include <stdio.h>

int add(int a, int b){
  int c;
  c = a + b;
  return c;
}

//相当于创建了一个类型,名字叫做func。这个func表示的是一个函数指针类型
typedef int (*func)(int, int);

int main(int argc, char const *argv[]) {
  //声明一个func类型的函数指针p,指向add函数
  func p = add;
  printf("2 + 3 = %d\n", p(2, 3)); //2 + 3 = 5
  return 0;
}

使用回调函数

下面来看看如何使用回调函数,说白了就是把一个函数指针作为函数的参数

#include <stdio.h>

char *evaluate(int score){
  if (score < 60 && score >= 0){
    return "不及格";
  }else if (score < 80){
    return "及格";
  }else if (score < 90){
    return "不错";
  }else if (score <=100){
    return "真棒";
  }else {
    return "无效的成绩";
  }
}

//接收一个整型和一个函数,函数接收一个整型返回char *
char *execute1(int score, char *(*f)(int)){
  return f(score);
}

//除了上面那种方式,我们还可以跟之前一样通过typedef
typedef char *(*func)(int);
//这样声明也是可以的。
char *execute2(int score, func f){
  return f(score);
}

int main(int argc, char const *argv[]) {
  printf("%s\n", execute1(88, evaluate)); //不错
  printf("%s\n", execute2(70, evaluate)); //及格
}

python向C语言传递回调函数

我们知道了在C中传入一个函数,那么在python中如何定义一个C语言可以识别的函数呢?毫无疑问,类似于结构体,我们肯定是要先定义一个python的函数,然后再把python的函数转化成C语言可以识别的函数。

int add(int a, int b, int (*f)(int *, int *)){
  return f(&a, &b);
}

我们就以这个函数为例,add函数返回一个int,接收两个int,和一个函数指针,那么我们如何在python中定义这样的函数并传递呢?我们来看一下,不过我们记得要编译成扩展模块:gcc?-o dll或者so -shared c源文件,这里编译成mmp.dll

from ctypes import *

lib = CDLL("./mmp.dll")

# 扩展函数中接收的函数的参数是两个int *,所以我们这里的a和b也是一个pointer
def add(a, b):
    return a.contents.value + b.contents.value

# 此时我们把C中的函数用python表达了,但是这样肯定是不可能直接传递的,能传就见鬼了
# 那我们要如何转化呢?
# 可以通过ctypes里面的函数CFUNCTYPE转化一下,这个函数接收任意个参数
# 但是第一个参数是函数的返回值类型,然后函数的参数写在后面,有多少写多少。
# 比如这里的函数返回一个int,接收两个int *,所以就是
t = CFUNCTYPE(c_int, POINTER(c_int), POINTER(c_int))
# 如果函数不需要返回值,那么写一个None即可
# 然后得到一个类型t,此时的类型t就等同于C中的 typedef int (*t)(int*, int*);
# 将我们的函数传进去,就得到了C语言可以识别的函数func
func = t(add)
# 然后调用,别忘了定义返回值类型,当然这里是int就无所谓了
lib.add.restype = c_int
print(lib.add(88, 96, func))
print(lib.add(59, 55, func))
print(lib.add(94, 105, func))
"""
184
114
199
"""

原文地址:https://www.cnblogs.com/traditional/p/12242990.html

时间: 2024-11-03 16:14:57

ctypes给扩展模块中的函数传递回调函数的相关文章

ctypes获取扩展模块中函数的返回值

ctypes获取返回值 我们前面已经看到了,通过ctypes像扩展模块中的函数传参时是没有问题的,但是我们如何拿到返回值呢?我们之前都是使用printf直接打印的,但是这样显然不行,我们肯定是要拿到返回值去做一些别的事情的.那么我们看看如何使用ctypes获取函数的返回值. 获取整型返回值 int test1(int a, int b) { int c; c = a + b; return c; } void test2() { } 我们定义了两个函数,下面编译成dll文件,dll文件名叫做mm

iOS中什么是BLOCK回调函数

1.回调函数类似通知.委托 2.回调函数声明.实现.回调可以在都一个类中,也可以把回调写到别的类中 3.在A类中声明函数,在实现函数中,达到满足的条件,回调,在B类中的回调函数会被调用,并去处理满足条件的事情 比如下载,如果下载完成,就触发回调函数,通知B类中的回调函数,传递一个下载完成的参数,B类的回调函数会根据参数       执行相应的代码,如果成功怎么样怎么样,如果失败怎么样怎么样,B类在A类下载过程中完全可以做他自己的事情. 4.例子(伪代码): A类a.h中声明 -(void)dow

Java/Android中的函数调用&amp;回调函数&amp;自定义回调函数

在做Android自定义控件时遇到要自定义回调函数的问题,想想自己还暂时没有那么精深的技术,赶紧返过头回来再重新研究Java中回调函数的问题.然而不幸的是,网上太多杂乱的帖子和博客都是转来转去,而且都是那一篇"C中的回调函数.....指针.....java....",一点看不出来是自己的思路,估计都是哪哪哪抄来的!(呵呵,要么就是吐槽对了,要么就是我水平太烂读不懂还妄加评论)还有一些很不错的文章,我会在最后参考中加上链接,大家可以看看. 那么来开始我们的正题--什么是回调函数? 我们一

C++中类成员函数作为回调函数

注:与tr1::function对象结合使用,能获得更好的效果,详情见http://blog.csdn.net/this_capslock/article/details/38564719 回调函数是基于C编程的Windows SDK的技术,不是针对C++的,程序员可以将一个C函数直接作为回调函数,但是如果试图直接使用C++的成员函数作为回调函数将发生错误,甚至编译就不能通过. 普通的C++成员函数都隐含了一个传递函数作为参数,亦即“this”指针,C++通过传递一个指向自身的指针给其成员函数从

钩子函数 和回调函数

http://blog.csdn.net/lipeionline/article/details/6369657  转自 也可以这样,更容易理解:回调函数就好像是一个中断处理函数,系统在符合你设定的条件时自动调用.为此,你需要做三件事: 1.       声明: 2.       定义: 3.       设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用. 钩子实际上是一个处理消息的程序段,通过系统调用,把它挂入系统.每当特定的消息发出,在没有到达目的窗口前

什么是回调函数?回调函数适合在什么情况下使用?

一直不太理解回调函数的作用,下面是找到的一些关于回调函数的作用的解答. 1.回调函数是一个很有用,也很重要的概念.当发生某种事件时,系统或其他函数将会自动调用你定义的一段函数. 2.回调函数就相当于一个中断处理函数,由系统在符合你设定的条件时自动调用.为此,你需要做三件事:1,声明:2,定义:3,设置触发条件,就是在你的函数中把你的回调函数名称转化为地址作为一个参数,以便于系统调用. 3.所谓回调函数就是按照一定的形式由你定义并编写实现内容,当发生某种事件时,而由系统或其它函数来调用的函数.使用

c语言(函数指针,回调函数)

//  main.m //  1-28随堂笔记 //讲师: 小辉 //笔者: 王学文 //  Created by lanouhn on 15/1/28. //  Copyright (c) 2015年 lanouhn. All rights reserved. // 函数指针, 回调函数 #import <Foundation/Foundation.h> struct student { char name[20]; float score; int age; }; typedef stru

钩子函数和回调函数的区别

一般认为,钩子函数就是回调函数的一种,其实还是有差异的,差异地方就是:触发的时机不同. 先说钩子函数: 钩子(Hook)概念源于Windows的消息处理机制,通过设置钩子,应用程序对所有消息事件进行拦截,然后执行钩子函数. let btn = document.getElementById("btn"); btn.onclick = () => { console.log("i'm a hook"); } 上面的例子,在按钮点击时候立即执行钩子函数.而看下面的

普通函数与回调函数的区别

普通函数与回调函数的区别:对普通函数的调用:调用程序发出对普通函数的调用后,程序执行立即转向被调用函数执行,直到被调用函数执行完毕后,再返回调用程序继续执行.从发出调用的程序的角度看,这个过程为“调用-->等待被调用函数执行完毕-->继续执行” 对回调函数调用:调用程序发出对回调函数的调用后,不等函数执行完毕,立即返回并继续执行.这样,调用程序执和被调用函数同时在执行.当被调函数执行完毕后,被调函数会反过来调用某个事先指定函数,以通知调用程序:函数调用结束.这个过程称为回调(Callback)