python - 构建 Python C 扩展

标签 python c windows build compiler-errors

我需要创建一个新的 python 模块作为性能和 CUDA 利用率的 c 扩展。我为此尝试了几个教程,但没有成功。这是我的文件:

hellomodule.c

#include <Python.h>

static PyObject* say_hello(PyObject* self, PyObject* args)
{
    const char* name;

    if (!PyArg_ParseTuple(args, "s", &name))
        return NULL;

    printf("Hello %s!\n", name);

    Py_RETURN_NONE;
}

static PyMethodDef HelloMethods[] =
{
     {"say_hello", say_hello, METH_VARARGS, "Greet somebody."},
     {NULL, NULL, 0, NULL}
};

PyMODINIT_FUNC inithello(void)
{
     (void) Py_InitModule("hello", HelloMethods);
}

setuphello.py

from distutils.core import setup, Extension

module1 = Extension('hello', sources = ['hellomodule.c'])

setup (name = 'PackageName',
    version = '1.0',
        description = 'This is a demo package',
        ext_modules = [module1])

这是我对 python setuphello.py build 的结果:

running build
running build_ext
building 'hello' extension
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\cl.exe /c /nologo /Ox /W3 /GL /DNDEBUG /MD -IC:\Anaconda3\include -IC:\Anaconda3\include "-IC:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\INCLUDE" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.10240.0\ucrt" "-IC:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\include\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.10240.0\shared" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.10240.0\um" "-IC:\Program Files (x86)\Windows Kits\10\include\10.0.10240.0\winrt" "-IC:\Program Files (x86)\IntelSWTools\Trace Analyzer and Collector\9.1.2.024\include" /Tchellomodule.c /Fobuild\temp.win32-3.5\Release\hellomodule.obj
hellomodule.c
hellomodule.c(23): warning C4013: 'Py_InitModule' undefined; assuming extern returning int
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\BIN\link.exe /nologo /INCREMENTAL:NO /LTCG /DLL /MANIFEST:EMBED,ID=2 /MANIFESTUAC:NO /LIBPATH:C:\Anaconda3\libs /LIBPATH:C:\Anaconda3\PCbuild\win32 "/LIBPATH:C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\LIB" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.10240.0\ucrt\x86" "/LIBPATH:C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6.1\lib\um\x86" "/LIBPATH:C:\Program Files (x86)\Windows Kits\10\lib\10.0.10240.0\um\x86" /EXPORT:PyInit_hello build\temp.win32-3.5\Release\hellomodule.obj /OUT:build\lib.win32-3.5\hello.cp35-win32.pyd /IMPLIB:build\temp.win32-3.5\Release\hello.cp35-win32.lib
LINK : error LNK2001: unresolved external symbol PyInit_hello
build\temp.win32-3.5\Release\hello.cp35-win32.lib : fatal error LNK1120: 1 unresolved externals
error: command 'C:\\Program Files (x86)\\Microsoft Visual Studio 14.0\\VC\\BIN\\link.exe' failed with exit status 1120

我查看了其他人遇到的各种错误,并尝试按照他们的调试逻辑进行操作,但老实说,我对导致我的错误的幕后发生的事情一无所知。我正在使用 Python 3.5 32 位 (Anaconda),因此一直在尝试使用 Visual C++ 构建工具及其打包的终端进行编译。但是,这没有任何区别。有人可以引导我朝着正确的方向前进吗?

最佳答案

您的方法的问题是您在使用 Python 3.5.x 解释器时依赖 Python 2.7.x 的教程/指南(可能是 this?)。

构造C扩展的方法有changed在 Python 3.x 中。

因此,为了编译您的“hello”模块,您必须在 hellomodule.c 中进行适当的更改:

首先,在 inithello() 函数的正上方添加以下 struct:

static struct PyModuleDef hellomodule = {
    PyModuleDef_HEAD_INIT,
    "hello", /* module name */
    NULL, /* module documentation, may be NULL */
    -1,
    HelloMethods /* the methods array */
};

然后将整个 inithello() 函数替换为:

PyMODINIT_FUNC PyInit_hello(void)
{
    return PyModule_Create(&hellomodule);
}

您无需对 setuphello.py 脚本进行任何更改,您可以照常运行该脚本:

python setuphello.py 构建


您可以通过进入build\lib.win32-3.5 目录(或类似目录)快速测试新编译的模块,复制.pyd 文件(在我的系统中它被命名为 hello.cp35-win32.pyd)放在方便的地方并且使用类似这个小脚本的东西(usehello.py>):

import hello

def greet(person):
    hello.say_hello(person)

greet("stranger")

运行 yield :

c:\>python usehello.py
Hello stranger!

c:\>

有关扩展程序的完整说明,您可以go到 Python 3.5 的官方文档

关于python - 构建 Python C 扩展,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38155988/

相关文章:

无论操作数和运算符如何,PHP MySQL 比较始终为真

python - 为什么我的 boost http 客户端无法连接到 python http 服务器?

c - 如何让EUDC在不重启的情况下生效?

c - 为什么我不能声明一个已经定义了结构的变量?

c# - Windows 服务和 Win 应用程序之间的通信

C++ strtok 跳过第二个标记或连续分隔符

python - 在 Google App Engine 上使用自定义域进行 Web2py 身份验证?

python - 使用GPIO通过按钮控制树莓派picamera

python - 当我从我的 Django 应用程序中将它们设置为 ‘print’ 时,它们会去哪里?

c - 在 EC2 上运行 C 模拟