天天看點

使用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);

        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>

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,打開聽聽看是否是你想要的歌曲呢,呵呵。。。 

本文轉自Phinecos(洞庭散人)部落格園部落格,原文連結:http://www.cnblogs.com/phinecos/archive/2010/05/22/1741667.html,如需轉載請自行聯系原作者