

INBUFSIZE=4096
if__name__=='__main__':
encoder=clame.Encoder('test.mp3')
input=file('test.raw','rb')
data=input.read(INBUFSIZE)
whiledata!='':
encoder.encode(data)
data=input.read(INBUFSIZE)
input.close()
encoder.close()
再来看C扩展模块这一端,下面是完整的代码:


#include<lame.h>
typedefstruct{
PyObject_HEAD
FILE*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);
}
if(self->outfp){
fclose(self->outfp);
}
self->ob_type->tp_free(self);
}
staticintEncoder_init(clame_EncoderObject*self,PyObject*args,PyObject*kw){
char*outPath;
if(!PyArg_ParseTuple(args,"s",&outPath)){
return-1;
}
if(self->outfp||self->gfp){
PyErr_SetString(PyExc_Exception,"__init__alreadycalled");
return-1;
}
self->outfp=fopen(outPath,"wb");
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){
fwrite(mp3_buffer,1,mp3_bytes,self->outfp);
}
}
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){
fwrite(mp3_buffer,1,mp3_bytes,self->outfp);
}
free(mp3_buffer);
lame_close(self->gfp);
self->gfp=NULL;
fclose(self->outfp);
self->outfp=NULL;
Py_RETURN_NONE;
}
staticPyMethodDefEncoder_methods[]={
{"encode",(PyCFunction)Encoder_encode,METH_VARARGS,"encodesandwritesdatatotheoutputfile."},
{"close",(PyCFunction)Encoder_close,METH_NOARGS,"closetheoutputfile."},
{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,"Mysecondlamemodule.");
Py_INCREF(&clame_EncoderType);
PyModule_AddObject(m,"Encoder",(PyObject*)&clame_EncoderType);
}
编译过程:
首先定义了clame_EncoderObject结构体,这个结构体就是用来存储状态信息的,字段outfp用来存储输出文件,gfp则保存lame的状态,可以用来检查是否已经是重复调用已经调用过的函数了。
为了创建这个结构体的一个新实例,我们需要定义Encoder_new函数,你可以把这个函数视为Python里的__new__方法,当Python解释器需要创建你定义的类型的新实例时就会去调用这个方法。在这个方法里没作什么操作,仅仅是做初始化工作,把outfp和gfp都设置为NULL,此外,与Encoder_new函数对应,还需要定义Encoder_dealloc方法来对实例进行析构,你可以把这个函数视为Python的__del__方法,clame_EncoderType结构体则是真正定义了我们的Encoder对象,它的各个字段指定了_new,_close,_encode,_dealloc等方法。在initclame方法中,PyModuleObject则实际指定了在Python程序中使用的Encoder对象。