麻烦gcc链接器 - 为python编译c函数

时间:2014-07-10 22:33:05

标签: python c gcc linker

我正在尝试编译我在github上找到的一些基于c的视频解码器函数,以便在python中将它们作为函数运行。不幸的是,我遇到了gcc链接器问题。我在我的脸上很平坦,从命令行编译c(我曾经在eclipse中做过一次)。

以下是我从命令行运行的内容

gcc -dynamiclib -I/usr/include/python2.7/ -lpython2.7 -o _decoder.dylib _decoder.c

我还尝试添加这些选项,以帮助链接器找到.c和.h文件的链接,这些文件定义了"缺失"函数(都在同一目录中,其路径我将缩写为$ PATHTOCFILESDIR)

-I/$PATHTOCFILESDIR/uvlc-decoder.c
-I/$PATHTOCFILESDIR/uvlc-decoder.h

这是错误:

Undefined symbols for architecture x86_64: 
  "_Video_uvlc_decode_frame", referenced from:
    ___decode_uvlc_frame in _decoder-db7728.o 
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1

在与google一起审核之后,我查看了所有其他c和h文件,试图找出为什么gcc无法找到Video_uvlc_decode_frame函数,但它对我来说并不是立即透明的。我的唯一猜测是(这在下面显示)我注意到整个文件中有几行,如" FE_INTERNAL"我在C的知识之外发现了。我相信这是针对我的版本没有安装的Sphinx。这会导致这些链接器问题吗?

以下是相关代码的缩减:

链接器指向错误的文件的顶部:

  

_decoder.c

#include <string.h>
#include "idct8.h"
#include "uvlc-decoder.h"
#include "_decoder.h"


static PyObject *
__decode_uvlc_frame (
    PyObject *self,
    PyObject *args
)
{
    PyObject *input_buffer;

    if (!PyArg_ParseTuple(args, "S:decode_h263_uvlc", &input_buffer))
         return NULL;

    return Video_uvlc_decode_frame(input_buffer);
}

包含文件的声明(我认为)应该指向&#34;缺少&#34;功能:

  

UVLC-decoder.h

#ifndef __VIDEO_UVLC_DECODER_H__
#define __VIDEO_UVLC_DECODER_H__

#include <stdint.h>
#include <stdbool.h>

#include <Python.h>

#include "utils.h"


FE_INTERNAL
PyObject *
Video_uvlc_decode_frame (
    PyObject *input_buffer
);


#endif

编辑:我在目录中的另一个文件中找到了FE_INTERNAL的定义:

  

utils.h

#ifdef __GNUC__
#   define FE_LIKELY(x)    __builtin_expect((x), 1)
#   define FE_UNLIKELY(x)  __builtin_expect((x), 0)
#   define FE_INTERNAL     __attribute__((visibility("hidden")))
#else
#   define FE_LIKELY(x)    (x)
#   define FE_UNLIKELY(x)  (x)
#   define FE_INTERNAL
#endif

EDIT2:这本身并不透明,但我认为还有一个文件会改变答案。以下是相关信息:

  

UVLC-decoder.c

#include <stdlib.h>
#include <string.h>

#include "idct8.h"
#include "uvlc-decoder.h"
#include "uvlc-decoder-priv.h"

/*
number of other functions defined here that have been removed for brevity
*/

PyObject *
Video_uvlc_decode_frame (
    PyObject *input_buffer
)
{
    __DecoderState  dec_state;
    PyObject       *picture_desc = NULL;

    dec_state.out_picture_buf = NULL;
    dec_state.bitstream = FeDrone_BitStreamReader_new(input_buffer);

    if (FE_LIKELY(__decoder_read_frame(&dec_state))) {
        picture_desc = Py_BuildValue("(IIIs#)",
                                     dec_state.pic_header.width,
                                     dec_state.pic_header.height,
                                     dec_state.pic_header.frame_nr,
                                     (char *)dec_state.out_picture_buf,
                                     (int)dec_state.out_picture_len);
    }

    PyMem_FREE(dec_state.out_picture_buf);
    dec_state.out_picture_buf = NULL;

    Video_BitStreamReader_free(dec_state.bitstream);
    dec_state.bitstream = NULL;

    return picture_desc;
}

EDIT3:

我使用的终极gcc命令:

gcc -dynamiclib `python-config --cflags` `python-config --ldflags` -o _decoder.so *.c

这个命令将使用我正在开发的python框架的本地构建(macports build)。 * .c基本上告诉gcc在链接时使用当前文件夹中的所有.c文件。

1 个答案:

答案 0 :(得分:1)

你需要一个身体

FE_INTERNAL
PyObject *
Video_uvlc_decode_frame (
    PyObject *input_buffer
);

喜欢

 PyObject *
    Video_uvlc_decode_frame (
        PyObject *input_buffer
    )
{
 return input_buffer;
}