python如何调用C, 如何注册成C的回调函数(python后台程序常用方法)
2016-09-27 11:24
477 查看
最近做一个项目,分析视频内容,用C语言开发,需要运行在linux服务器后台,被python调用,并且实时返回进度信息;
python能调用C语言的函数;
python通过调用C函数,并注册python的回调函数,C代码通过python回调函数告诉Python当前实时进度和状态;
就像C语言编译出来的.so库只是python的一个模块,直接调用就可以了。
如何把这两个python函数注册成C代码的回调函数呢?
第一个参数是python回调函数的返回值,如果没有就是None。
第二个及其以后的就是python回调函数的参数类型了。
CMPRESULTFUNC = CFUNCTYPE(None, c_ulong, c_ulong, c_ulong, c_ulong)//创建一个c函数类型的对象工厂,该函数返回值为None,有三个入参,都为unsigned long。
CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback)根据Python可调用对象生成函数。
mylib.VideoAnalyzeStart(ulHandle, CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback), CMPSTATEFUNC(OnPyVideoStateCallback))//设置回调函数
但是如何确定python函数参数与C函数参数的对应关系呢?
一个大坑:需要注意CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback)这个指针函数是有自己的生存空间的,如果生存空间已过,会被释放,C代码再回调的时候,就会使用一个过期指针。
这里建议使用一个全局的python指针。
CMPRESULTFUNC = CFUNCTYPE(c_int, c_ulong, c_ulong, c_ulong, c_ulong)
CMPSTATEFUNC = CFUNCTYPE(c_int, c_ulong, c_ulong, c_ulong)
pResutFunc = CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback)
pStateFunc = CMPSTATEFUNC(OnPyVideoStateCallback)
def main():
global pResutFunc
global pStateFunc
....
iRet = mylib.VideoAnalyzeStart(ulHandle, pResutFunc, pStateFunc)见官网的解释:https://docs.python.org/3/library/ctypes.html#ctypes.c_long
Note
Make sure you keep references to
as long as they are used from C code.
and if you don’t, they may be garbage collected, crashing your program when a callback is made.
Also, note that if the callback function is called in a thread created outside of Python’s control (e.g. by the foreign code that calls the callback), ctypes creates a new dummy Python thread on every invocation. This behavior is correct for most purposes,
but it means that values stored with
across different callbacks, even when those calls are made from the same C thread.
其实是python后台程序常用方法:
C开发完成底层的功能,python直接把C当做python模块进行调用。
需要做两个工作:python通过调用C函数,并注册python的回调函数,C代码通过python回调函数告诉Python当前实时进度和状态;
1,python如何调用C语言
主要就是应用ctypes这个模块,too simple too naive。python代码是这样滴:
from ctypes import * dynamicLibString = './libcheckVideoFile.so' mylib = cdll.LoadLibrary(dynamicLibString) ulHandle = mylib.VideoAnalyzeInit(videoFilename) if ulHandle == 0: print 'VideoAnalyzeInit error.' print '' mylib.EnableBlackDetected(ulHandle) mylib.EnablePureColorDetected(ulHandle) mylib.EnableFrozenDetected(ulHandle) mylib.EnableMuteVoiceDetected(ulHandle)
C代码是这样滴:
unsigned long VideoAnalyzeInit(char* szFilename) { VideoAnalyzeManage* pManager = new VideoAnalyzeManage(szFilename); if(pManager) { int iRet = pManager->Init(); if(iRet != 0) { delete pManager; return 0; } } return (unsigned long)pManager; } void EnableBlackDetected(unsigned long ulHandle) { VideoAnalyzeManage* pManager = (VideoAnalyzeManage*)ulHandle; if(pManager) { pManager->EnableBlackDetected(); } }
就像C语言编译出来的.so库只是python的一个模块,直接调用就可以了。
2,python注册C语言的回调函数
其实也不难,python的函数本身也是python的对象,实现也就简单了:python的回调函数:
def OnPyVideoAnalyzeResultCallback(ulStartTS, ulEndTS, ulDetectedType, ulParam): fStartTS = ulStartTS/1000.0 fEndTS = ulEndTS/1000.0 outputString = '' if ulDetectedType == ALL_BLACK_DETECTED : outputString = videoFilename + ': All black color detected: start(' + str(fStartTS) + ') end(' + str(fEndTS) + ')' elif ulDetectedType == SIMPLE_COLOR_DETECTED : outputString = videoFilename + ': All pure color detected: start(' + str(fStartTS) + ') end(' + str(fEndTS) + ')' elif ulDetectedType == FROZEN_VIDEO_DETECTED : outputString = videoFilename + ': Frozen image detected: start(' + str(fStartTS) + ') end(' + str(fEndTS) + ')' elif ulDetectedType == AUDIO_MUTE_DETECTED : outputString = videoFilename + ': Mute voice detected: start(' + str(fStartTS) + ') end(' + str(fEndTS) + ')' print outputString WriteLog(logFilename, outputString) def OnPyVideoStateCallback(uiProgress, uiState, ulParam): global videoFilename outputString = '' if uiState == DECODE_START : outputString = '\r\n' + videoFilename + ': video analyze is starting......' WriteLog(logFilename, outputString) elif uiState == DECODE_RUNNING : outputString = videoFilename + ': video analyze is running, progress: ' + str(uiProgress) + '%' elif uiState == DECODE_END : outputString = videoFilename + ': video analyze is ended' WriteLog(logFilename, outputString) elif uiState == DECODE_ERROR : outputString = videoFilename + ': video analyze is error' WriteLog(logFilename, outputString) print outputStringpython 两个回调函数:OnPyVideoAnalyzeResultCallback和OnPyVideoStateCallback。
如何把这两个python函数注册成C代码的回调函数呢?
python部分是这样注册滴:
CMPRESULTFUNC = CFUNCTYPE(None, c_ulong, c_ulong, c_ulong, c_ulong) CMPSTATEFUNC = CFUNCTYPE(None, c_ulong, c_ulong, c_ulong) iRet = mylib.VideoAnalyzeStart(ulHandle, CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback), CMPSTATEFUNC(OnPyVideoStateCallback))应用这个来设置:CFUNCTYPE
第一个参数是python回调函数的返回值,如果没有就是None。
第二个及其以后的就是python回调函数的参数类型了。
CMPRESULTFUNC = CFUNCTYPE(None, c_ulong, c_ulong, c_ulong, c_ulong)//创建一个c函数类型的对象工厂,该函数返回值为None,有三个入参,都为unsigned long。
CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback)根据Python可调用对象生成函数。
mylib.VideoAnalyzeStart(ulHandle, CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback), CMPSTATEFUNC(OnPyVideoStateCallback))//设置回调函数
C部分是这样的:
int VideoAnalyzeStart(unsigned long ulHandle, AnalyzeDetectedCallback resultCallback, AnalyzeStateCallback stateCallback) { VideoAnalyzeManage* pManager = (VideoAnalyzeManage*)ulHandle; if(pManager) { pManager->SetAnalyzeResultCallback(resultCallback, 0); pManager->SetStateNotifyCallback(stateCallback, 0); int iRet = pManager->Start(); return iRet; } return -1; }C部分不用管。
但是如何确定python函数参数与C函数参数的对应关系呢?
python函数参数与C函数参数的对应表(其实也可以叫ctypes类型表):
一个大坑:需要注意CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback)这个指针函数是有自己的生存空间的,如果生存空间已过,会被释放,C代码再回调的时候,就会使用一个过期指针。
这里建议使用一个全局的python指针。
CMPRESULTFUNC = CFUNCTYPE(c_int, c_ulong, c_ulong, c_ulong, c_ulong)
CMPSTATEFUNC = CFUNCTYPE(c_int, c_ulong, c_ulong, c_ulong)
pResutFunc = CMPRESULTFUNC(OnPyVideoAnalyzeResultCallback)
pStateFunc = CMPSTATEFUNC(OnPyVideoStateCallback)
def main():
global pResutFunc
global pStateFunc
....
iRet = mylib.VideoAnalyzeStart(ulHandle, pResutFunc, pStateFunc)见官网的解释:https://docs.python.org/3/library/ctypes.html#ctypes.c_long
Note
Make sure you keep references to
CFUNCTYPE()objects
as long as they are used from C code.
ctypesdoesn’t,
and if you don’t, they may be garbage collected, crashing your program when a callback is made.
Also, note that if the callback function is called in a thread created outside of Python’s control (e.g. by the foreign code that calls the callback), ctypes creates a new dummy Python thread on every invocation. This behavior is correct for most purposes,
but it means that values stored with
threading.localwill not survive
across different callbacks, even when those calls are made from the same C thread.
相关文章推荐
- python如何调用C, 如何注册成C的回调函数(python后台程序常用方法)
- python中如何调用shell 中OS.SYSTEM等方法
- 如何在Python中调用父类的同名方法
- python 常用读取文件调用方法
- python如何通过实例方法名字调用方法
- Linux下python如何调用c++的代码,用ctypes方法。。
- [zz]如何在Python中调用父类的同名方法
- python 安装模块的常用方法及如何查看已安装的模块
- python_如何通过实例方法名字调用方法?
- 常用js,css文件统一加载方法(推荐) 并在加载之后调用回调函数
- Python中实例对象如何进行属性和方法调用原因分析
- python中如何调用shell 中OS.SYSTEM等方法
- struts2 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用
- C/C++中如何调用Python方法
- Python常用数据类型方法调用
- 转帖:C/C++中如何调用Python方法
- python中如何调用shell 中OS.SYSTEM等方法
- 在Python常用模块I如何打开相关文件的方法
- python使用multiprocessing模块实现带回调函数的异步调用方法
- Python调用C函数的方法以及如何编写Python的C扩展