【问题标题】:Issues compiling C code for a Python module为 Python 模块编译 C 代码的问题
【发布时间】:2014-10-02 20:10:47
【问题描述】:

我有一个 Python 脚本,它将打开并解析一些 DAT 文件,其中包含压缩(QFS 压缩,因此没有内置函数来处理它)十六进制数据。我在 Github 上找到了一个 C 语言脚本,它既可以解压缩又可以重新压缩,并且打算从 Python 中调用。

Canopy 的 Python 2.7 在我的 Win8.1 64 位机器上编译 C 代码时表现不佳。它确实编译时出错,但在调用时会导致内核崩溃,然后我必须重新编译,否则会出现 dll 错误(它找到了 dll 但无法使用它)。

所以我通过 Anaconda 安装了 Python 3.4。它在我的机器上运行良好,但在编译过程中出现错误。

这似乎是最后的相关 C 代码。缺少的代码是实际使用的算法。 代码本身可以在 https://github.com/wouanagaine/SC4Mapper-2013/blob/master/Modules/qfs.c 如果你需要更多。 setup.py 代码位于同一个“模块”文件夹中,如果您想查看的话。

static PyObject *QFSEncode( PyObject *self, PyObject *args )
{
    char* buffer;
    unsigned char* bufferIn;
    int len;
    unsigned char* out;
    PyObject *pRet ;
    if (!PyArg_ParseTuple(args, "s#", &buffer, &len))
        return NULL;
    out = (unsigned char*)malloc( len*2 );
    bufferIn = (unsigned char*)malloc( len + 2000 );
    memcpy( bufferIn, buffer, len );
    compress_data( (unsigned char*)bufferIn, &len, out);
    pRet = Py_BuildValue( "s#", out, len ); 
    free( out );
    free( bufferIn );
    return pRet;
}

static PyObject *QFSDecode( PyObject *self, PyObject *args )
{
    char* buffer;
    int len;
    unsigned char* out;
    PyObject *pRet ;
    if (!PyArg_ParseTuple(args, "s#", &buffer, &len))
        return NULL;
    out = uncompress_data( (unsigned char*)buffer, &len);
    pRet = Py_BuildValue( "s#", out, len ); 
    free( out );
    return pRet;
}


static PyMethodDef QFSMethods[] =
{
    {"decode", QFSDecode, METH_VARARGS, "decode a buffer" },
    {"encode", QFSEncode, METH_VARARGS, "encode a buffer" },
    {NULL, NULL, 0, NULL}        /* Sentinel */
};


PyMODINIT_FUNC initQFS(void)
{
    (void) Py_InitModule("QFS", QFSMethods);
}

当我尝试编译它时得到这个返回

C:\Users\John\Desktop\DAT>python setup.py install
running install
running build
running build_ext
building 'QFS' extension
C:\strawberry\c\bin\gcc.exe -mdll -O -Wall -IC:\Anaconda3\include -IC:\Ana
\include -c qfs.c -o build\temp.win-amd64-3.4\Release\qfs.o
qfs.c: In function 'QFSEncode':
qfs.c:259:11: warning: pointer targets in assignment differ in signedness
nter-sign]
qfs.c: In function 'initQFS':
qfs.c:293:5: warning: implicit declaration of function 'Py_InitModule' [-W
it-function-declaration]
qfs.c:294:1: warning: control reaches end of non-void function [-Wreturn-t
qfs.c: In function 'compress_data':
qfs.c:184:32: warning: 'bestoffs' may be used uninitialized in this functi
maybe-uninitialized]
writing build\temp.win-amd64-3.4\Release\QFS.def
C:\strawberry\c\bin\gcc.exe -shared -s build\temp.win-amd64-3.4\Release\qf
ild\temp.win-amd64-3.4\Release\QFS.def -LC:\Anaconda3\libs -LC:\Anaconda3\
d\amd64 -lpython34 -lmsvcr100 -o build\lib.win-amd64-3.4\QFS.pyd
Cannot export PyInit_QFS: symbol not defined
build\temp.win-amd64-3.4\Release\qfs.o:qfs.c:(.text+0x98b): undefined refe
to `Py_InitModule'
collect2.exe: error: ld returned 1 exit status
error: command 'C:\\strawberry\\c\\bin\\gcc.exe' failed with exit status 1

这是第 259 行

bufferIn = (unsigned char*)malloc( len + 2000 );

我试着弄乱指针,但我对这样做没有信心。我确实设法让第一个错误消失,但我很确定我这样做破坏了代码功能。 我仍然得到第二个错误。

我对 Python 并不陌生,但这是我第一次涉足更高级别的 Python 编程。 我不会C,如果不是太复杂的话,我只能勉强跟着一些代码。

【问题讨论】:

  • 看起来Py_InitModule() 是未定义的,在这种情况下,您可能忘记将#include <Python.h> 放在C 文件的顶部。这可能会解决其他一些问题。
  • 感谢您的快速回复。该位确实位于 #include #include #include 的顶部
  • 那么您的系统有些问题。 (您确定您正确安装了 Python SDK 吗?)检查文件 Python.h 是否确实存在于编译器的 #include 搜索路径中的某个位置。
  • 看起来像链接器问题。快速浏览一下,您是在标题中还是在 .c 文件顶部提出声明?看起来一切都是从这一行开始的:qfs.c:293:5: warning: implicit declaration of function 'Py_InitModule' [-Wit-function-declaration] 尝试摆脱或警告(它们表明 99% 的代码中存在错误),同时您可能会修复编译。事实上,只要有可能,您就可以使用-WError 节省大量时间...

标签: python c compiler-errors


【解决方案1】:

Py_InitModule() 在 Python 3 中不存在,它或多或少被 PyModule_Create() 取代。见Porting Extension Modules to Python 3

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-07
    • 2014-07-12
    • 2020-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-04
    相关资源
    最近更新 更多