使用C语言扩展Python(三)

上一篇中我们已经了解如何在Python程序和C模块之间进行值的相互传递,现在我们来进入实作阶段,看看如何将一个C语言开发的开源mp3编解码库LAME包装为一个Python下可以使用的扩展模块。
首先去http://lame.sourceforge.net/download.php下载LAME的源代码,然后切换到root用户编译源代码,
./ configure
make
make install

安装完成后你可以在/usr/local/include/lame目录下找到lame.h头文件,我们在后面的demo程序中会include它的,下面就是一个非常简单的lame示例程序lame_test.c:

代码
#include  < stdio.h >
#include 
< stdlib.h >
#include 
< lame.h >

#define  INBUFSIZE 4096
#define  MP3BUFSIZE (int) (1.25 * INBUFSIZE) + 7200

int  encode( char *  inPath,  char *  outPath) {
    
int  status  =   0 ;
    lame_global_flags
*  gfp;
    
int  ret_code;
    FILE
*  infp;
    FILE
*  outfp;
    
short *  input_buffer;
    
int  input_samples;
    
char *  mp3_buffer;
    
int  mp3_bytes;
    
    gfp 
=  lame_init();
    
if  (gfp  ==  NULL) {
        printf(
" lame_init failed/n " );
        status 
=   - 1 ;
        
goto  exit;
    }
    
    ret_code 
=  lame_init_params(gfp);
    
if  (ret_code  <   0 ) {
        printf(
" lame_init_params returned %d/n " ,ret_code);
        status 
=   - 1 ;
        
goto  close_lame;
    }

    infp 
=  fopen(inPath,  " rb " );
    outfp 
=  fopen(outPath,  " wb " );
    
    input_buffer 
=  ( short * )malloc(INBUFSIZE * 2 );
    mp3_buffer 
=  ( char * )malloc(MP3BUFSIZE);
    
    
do {
        input_samples 
=  fread(input_buffer,  2 , INBUFSIZE, infp);
        mp3_bytes 
=  lame_encode_buffer_interleaved(gfp, input_buffer,input_samples / 2 , mp3_buffer, MP3BUFSIZE);
        
if  (mp3_bytes  <   0 ) {
            printf(
" lame_encode_buffer_interleaved returned %d/n " , mp3_bytes);
            status 
=   - 1 ;
            
goto  free_buffers;
        } 
else   if (mp3_bytes  >   0 ) {
            fwrite(mp3_buffer, 
1 , mp3_bytes, outfp);
        }
    }
while  (input_samples  ==  INBUFSIZE);
    
    mp3_bytes 
=  lame_encode_flush(gfp, mp3_buffer,  sizeof (mp3_buffer));
    
if  (mp3_bytes  >   0 ) {
        printf(
" writing %d mp3 bytes/n " , mp3_bytes);
        fwrite(mp3_buffer, 
1 , mp3_bytes, outfp);
    }
free_buffers:
    free(mp3_buffer);
    free(input_buffer);
    
    fclose(outfp);
    fclose(infp);
close_lame:
    lame_close(gfp);
exit:
    
return  status;
}

int  main( int  argc,  char **  argv) {
    
if  (argc  <   3 ) {
        printf(
" usage: lame_test rawinfile mp3outfile/n " );
    }
    encode(argv[
1 ], argv[ 2 ]);
    
return   0 ;
}

编译步骤:

gcc -I  / usr / local / include / lame lame_test . c -lmp3lame -o lame_test

试验准备:

首先需要一个test.wav文件,先安装sox来将wav文件转为raw格式的数据:

    sudo apt-get install sox
    sox test
. wav -t raw test . raw

 

然后执行lame_test来对其进行mp3编码:

./ lame_test  ./ test . raw  ./ test . mp3  

好了,现在我们要在这个c程序的基础上将其包装为一个Python扩展模块。下面的pylame.c就是简单地调用lame_test.c中定义的encode方法,然后通过它对外部的python程序提高mp3编码的服务

代码
#include  < Python.h >
#include  < lame.h >

int  encode( char *  , char * );

static  PyObject  *  pylame_encode(PyObject *  self, PyObject *  args) {
    
int  status;
    
char *  inPath;
    
char *  outPath;
    
if  ( ! PyArg_ParseTuple(args,  " ss " & inPath,  & outPath)) {        
        
return  NULL;
    }
    status  =  encode(inPath, outPath);
    
return  Py_BuildValue( " i " , status);
}

static  PyMethodDef pylame_methods[]  =  {
    { " encode " , pylame_encode, METH_VARARGS, NULL},
    {NULL, NULL,  0 , NULL}
};

PyMODINIT_FUNC initpylame() {
    Py_InitModule3( " pylame " , pylame_methods,  " an simple lame module. " );
}

模块编译步骤:

gcc -shared -I  / usr / include / python2 . 6  -I  / usr / local / include / lame /  pylame . c lame_test . c -lmp3lame -o pylame . so

ok,现在lame扩展模块已经封装好了,可以到python程序中进行调用了。在pylame.so所在目录下新建一个python文件lame1.py代码如下:

import  pylame

if   __name__   ==   ' __main__ ' :
    inPath  =   ' ./test.raw '
    outPath  =   ' ./test.mp3 '
    pylame.encode(inPath, outPath)

编译执行: 

python  ./ lame1 . py

你会发现生成了一个test.mp3,打开听听看是否是你想要的歌曲呢,呵呵。。。 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值