`
dato0123
  • 浏览: 918352 次
文章分类
社区版块
存档分类
最新评论

使用C语言扩展Python(五)

 
阅读更多
上一篇中我们在python端的做法是每次读取一个数据块,然后将这个数据块传递进C扩展模块中去,但对于目标文件的数据写入是在C扩展模块中完成的,但其实可以更面向对象一点,不是吗?原来outfp是一个文件指针,
不如改成一个从Python中传递一个文件对象到C模块里去,这个文件对象有自己的write方法,这样在C扩展模块中你就可以回调文件对象的write方法来完成数据的写入。
首先来看Python端的代码,我们定义了一个file类继承下来的MyFile子类,其中的write方法就是为在C扩展模块中回调而专门准备的。
代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->#!/usr/bin/envpython

importclame

INBUFSIZE
=4096

classMyFile(file):

def__init__(self,path,mode):
file.
__init__(self,path,mode)
self.n
=0

defwrite(self,s):
file.write(self,s)
self.n
+=1

output
=MyFile('test3.mp3','wb')
encoder
=clame.Encoder(output)
input
=file('test.raw','rb')

data
=input.read(INBUFSIZE)
whiledata!='':
encoder.encode(data)
data
=input.read(INBUFSIZE)

input.close()
encoder.close()
output.close()

print'output.writewascalled%dtimes'%output.n

再来看C模块的代码,clame_EncoderObject结构体中的outfp改成了PyObject类型的指针,相应的dealloc方法也做了调整,由于outfp是一个对象,因此需要对其引用计数进行减1操作,而以前的代码是直接调用fclose来直接关闭打开的目标文件。但现在我们只需要对其引用计数做减1操作,等到其为0的时候,在外部的python代码中就可以关闭这个文件对象。同样可以看到在init函数中有相应的引用计数加1的操作。在encode和close两个函数中,通过PyObject_CallMethod实现了对Python对象中指定方法的回调。

代码
<!--<br/ /><br/ />Code highlighting produced by Actipro CodeHighlighter (freeware)<br/ />http://www.CodeHighlighter.com/<br/ /><br/ />-->#include<Python.h>

#include
<lame.h>

/*
*OnLinux:
*gcc-shared-I/usr/include/python2.6-I/usr/local/include/lameclame.c/
*-lmp3lame-oclame.so
*
*
*/

typedef
struct{
PyObject_HEAD
PyObject
*outfp;
lame_global_flags
*gfp;
}clame_EncoderObject;

staticPyObject*Encoder_new(PyTypeObject*type,PyObject*args,PyObject*kw){
clame_EncoderObject
*self=(clame_EncoderObject*)type->tp_alloc(type,0);
self
->outfp=NULL;
self
->gfp=NULL;
return(PyObject*)self;
}

staticvoidEncoder_dealloc(clame_EncoderObject*self){
if(self->gfp){
lame_close(self
->gfp);
}
Py_XDECREF(self
->outfp);
self
->ob_type->tp_free(self);
}

staticintEncoder_init(clame_EncoderObject*self,PyObject*args,PyObject*kw){
PyObject
*outfp;
if(!PyArg_ParseTuple(args,"O",&outfp)){
return-1;
}
if(self->outfp||self->gfp){
PyErr_SetString(PyExc_Exception,
"__init__alreadycalled");
return-1;
}
self
->outfp=outfp;
Py_INCREF(self
->outfp);
self
->gfp=lame_init();
lame_init_params(self
->gfp);
return0;
}

staticPyObject*Encoder_encode(clame_EncoderObject*self,PyObject*args){
char*in_buffer;
intin_length;
intmp3_length;
char*mp3_buffer;
intmp3_bytes;
if(!(self->outfp&&self->gfp)){
PyErr_SetString(PyExc_Exception,
"encodernotopen");
returnNULL;
}
if(!PyArg_ParseTuple(args,"s#",&in_buffer,&in_length)){
returnNULL;
}
in_length
/=2;
mp3_length
=(int)(1.25*in_length)+7200;
mp3_buffer
=(char*)malloc(mp3_length);
if(in_length>0){
mp3_bytes
=lame_encode_buffer_interleaved(
self
->gfp,
(
short*)in_buffer,
in_length
/2,
mp3_buffer,
mp3_length
);
if(mp3_bytes>0){
PyObject
*write_result=PyObject_CallMethod(
self
->outfp,"write","(s#)",mp3_buffer,mp3_bytes);
if(!write_result){
free(mp3_buffer);
returnNULL;
}
Py_DECREF(write_result);
}
}
free(mp3_buffer);
Py_RETURN_NONE;
}

staticPyObject*Encoder_close(clame_EncoderObject*self){
intmp3_length;
char*mp3_buffer;
intmp3_bytes;
if(!(self->outfp&&self->gfp)){
PyErr_SetString(PyExc_Exception,
"encodernotopen");
returnNULL;
}
mp3_length
=7200;
mp3_buffer
=(char*)malloc(mp3_length);
mp3_bytes
=lame_encode_flush(self->gfp,mp3_buffer,sizeof(mp3_buffer));
if(mp3_bytes>0){
PyObject
*write_result=PyObject_CallMethod(
self
->outfp,"write","(s#)",mp3_buffer,mp3_bytes);
if(!write_result){
free(mp3_buffer);
returnNULL;
}
Py_DECREF(write_result);
}
free(mp3_buffer);
lame_close(self
->gfp);
self
->gfp=NULL;
self
->outfp=NULL;
Py_RETURN_NONE;
}

staticPyMethodDefEncoder_methods[]={
{
"encode",(PyCFunction)Encoder_encode,METH_VARARGS,
"Encodesandwritesdatatotheoutputfile."},
{
"close",(PyCFunction)Encoder_close,METH_NOARGS,
"Closestheoutputfile."},
{NULL,NULL,
0,NULL}
};

staticPyTypeObjectclame_EncoderType={
PyObject_HEAD_INIT(NULL)
0,/*ob_size*/
"clame.Encoder",/*tp_name*/
sizeof(clame_EncoderObject),/*tp_basicsize*/
0,/*tp_itemsize*/
(destructor)Encoder_dealloc,
/*tp_dealloc*/
0,/*tp_print*/
0,/*tp_getattr*/
0,/*tp_setattr*/
0,/*tp_compare*/
0,/*tp_repr*/
0,/*tp_as_number*/
0,/*tp_as_sequence*/
0,/*tp_as_mapping*/
0,/*tp_hash*/
0,/*tp_call*/
0,/*tp_str*/
0,/*tp_getattro*/
0,/*tp_setattro*/
0,/*tp_as_buffer*/
Py_TPFLAGS_DEFAULT,
/*tp_flags*/
"Myfirstencoderobject.",/*tp_doc*/
0,/*tp_traverse*/
0,/*tp_clear*/
0,/*tp_richcompare*/
0,/*tp_weaklistoffset*/
0,/*tp_iter*/
0,/*tp_iternext*/
Encoder_methods,
/*tp_methods*/
0,/*tp_members*/
0,/*tp_getset*/
0,/*tp_base*/
0,/*tp_dict*/
0,/*tp_descr_get*/
0,/*tp_descr_set*/
0,/*tp_dictoffset*/
(initproc)Encoder_init,
/*tp_init*/
0,/*tp_alloc*/
Encoder_new,
/*tp_new*/
0,/*tp_free*/
};

staticPyMethodDefclame_methods[]={
{NULL,NULL,
0,NULL}
};

PyMODINIT_FUNCinitclame(){
PyObject
*m;
if(PyType_Ready(&clame_EncoderType)<0){
return;
}
m
=Py_InitModule3("clame",clame_methods,"MythirdLAMEmodule.");
Py_INCREF(
&clame_EncoderType);
PyModule_AddObject(m,
"Encoder",(PyObject*)&clame_EncoderType);
}

分享到:
评论

相关推荐

    用C语言扩展Python的功能

    用C语言扩展Python的功能

    用C语言扩展Python的功能.pdf

    用C语言扩展Python的功能.pdf

    C语言扩展Python学习记录.zip

    C语言扩展Python学习记录

    使用C语言扩展Python程序的简单入门指引

    主要介绍了使用C语言扩展Python程序的简单入门指引,来自于IBM官网网站技术文档,需要的朋友可以参考下

    用C语音编写python的扩展模块,也就是python调c库

    NULL 博文链接:https://8366.iteye.com/blog/1575189

    硬件SPI 作为 Python 的 C 扩展_C语言_python_代码_下载

    SPI-Py:硬件 SPI 作为 Python 的 C 扩展 示例用法 下面的命令可以在test_script.py文件中找到。 安装库后,通过以下方式将 spi 模块导入 Python 代码: 更多详情、使用方法,请下载后阅读README.md文件

    Extend_Python:C语言扩展Python学习记录

    Extend Python with C 实际上ctypes、Python C API或者基于API的Cython,逻辑都是: 接收Python对象-&gt;转换为C对象-&gt;调用C函数-&gt;返回值转换为Python对象-&gt;返回 的流程,较为值得关切的几点是: 指针传参问题 数组传递...

    使用C语言来扩展Python程序和Zope服务器的教程

    有几个原因使您可能想用 C 扩展 Zope...此外,扩展 Python 会给您带来其它的好处,因为您的代码将可以从任何 Python 脚本访问,而不只是从 Zope。这里唯一要提醒的是在写本文的时候,Python 的当前版本是 2.1,但是 Zop

    课程设计-使用python对c语言代码进行静态分析.zip

    课程设计-使用python对c语言代码进行静态分析.zip 项目资源具有较高的学习借鉴价值,也可直接拿来修改复现。可以在这些基础上学习借鉴进行修改和扩展,实现其它功能。 可下载学习借鉴,你会有所收获。 课程设计-使用...

    数据结构(基于 C++ 语言) + 算法 (基于 C语言 和 Python语言).zip

    对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】: 有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。 鼓励下载和使用,并欢迎大家互相学习,共同...

    用Cython加速Python到“起飞”(推荐)

    Cython是让Python脚本支持C语言扩展的编译器,Cython能够将Python+C混合编码的.pyx脚本转换为C代码,主要用于优化Python脚本性能或Python调用C函数库。由于Python固有的性能差的问题,用C扩展Python成为提高Python...

    如何用C代码给Python写扩展库(Cython)

    之前一篇文章里提到了利用Cython来编译Python,这次来讲一下如何用Cython给Python写扩展库。 两种语言混合编程,其中最重要的是类型的传递。 我们用一个简单的例子进行入门:这次的目标是用C语言写一个Numpy的加法和...

    python 3.10.5 Windows 64位安装包

    Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。 [4] Python 也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码...

    python 3.10.5 MacOS 64位安装包

    Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。 [4] Python 也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码...

    python程序的格式以及扩展名

    Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。Python也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或机器...

    C对Python进行扩展的详细步骤

    详细记录了windows下C语言对python进行扩展的整个过程。step by step,步骤详细,欢迎交流。

    python最新安装包-3.10.7-amd64.zip

    Python解释器易于扩展,可以使用C语言或C++(或者其他可以通过C调用的语言)扩展新的功能和数据类型。 [4] Python也可用于可定制化软件中的扩展程序语言。Python丰富的标准库,提供了适用于各个主要系统平台的源码或...

Global site tag (gtag.js) - Google Analytics