【发布时间】:2018-11-26 18:10:31
【问题描述】:
我用 C 语言编写了一个名为 extmodule.c 的扩展模块,其代码如下:
#include <Python.h>
//Define a new exception object for our module
static PyObject *extError;
static PyObject* ext_cpu(PyObject* self, PyObject *args)
{
int pid;
int sts=0;
//We expect at least 1 argument to this function
if(!PyArg_ParseTuple(args, "i", &pid))
{
return NULL;
}
printf("Hello, from C World! Pid: %i", pid);
sts=pid;
return Py_BuildValue("i", sts);
}
static PyMethodDef ext_methods[] = {
//PythonName, C-FunctionName, argument_presentation, description
{"cpu", ext_cpu, METH_VARARGS, "Print cpu consumption of a particular process with pid"}
};
PyMODINIT_FUNC
PyInit_ext(void)
{
PyObject *m;
m = PyModule_Create(&ext_methods);
if (m == NULL)
return NULL;
extError = PyErr_NewException("spam.error", NULL, NULL);
Py_INCREF(extError);
PyModule_AddObject(m, "error", extError);
return m;
}
之后我创建了一个setup.py来在我的python程序中构建和安装扩展文件,setup.py的代码如下:
from distutils.core import setup, Extension
module1 = Extension('ext',
include_dirs = ['/usr/local/include'],
libraries = ['pthread'],
sources = ['extmodule.c'])
setup (name = 'ext',
version = '1.0',
description = 'This is a C extension for Python program',
author = 'Somdip Dey',
url = '',
ext_modules = [module1])
现在在命令提示符下,我使用以下命令构建了 setup.py:
>> python setup.py build
运行构建 运行 build_ext
构建“ext”扩展 gcc -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -Wstrict-prototypes -I/Users/somdipdey/ anaconda3/include -arch x86_64 -I/Users/somdipdey/anaconda3/包括 -arch x86_64 -I/usr/local/include -I/Users/somdipdey/anacon nda3/include/python3.6m -c extmodule.c -o 构建/temp.macosx-10.7-x86_64-3.6/extmodule.o extmodule.c:34:25: 警告:不兼容的指针类型将 'PyMethodDef (*)[1]' 传递给 类型参数 'struct PyModuleDef *' [-Wincompatible-pointer-types] m = PyModule_Create(&ext_methods); /Users/somdipdey/anaconda3/include/python3.6m/modsupport.h:158:26: 注意:从宏“PyModule_Create”扩展而来 PyModule_Create2(模块,PYTHON_API_VERSION) ^~~~~~ /Users/somdipdey/anaconda3/include/python3.6m/modsupport.h:150:60: 注意:在此处将参数传递给参数 PyAPI_FUNC(PyObject ) PyModule_Create2(struct PyModuleDef, ^ 1 个警告生成。 gcc -bundle -undefined dynamic_lookup -L/用户/somdipdey/anaconda3/lib -arch x86_64 -L/用户/somdipdey/anaconda3/lib -arch x86 _64 -arch x86_64 build/temp.macosx-10.7-x86_64-3.6/extmodule.o -L/Users/somdipdey/anaconda3/lib -lpthread -o build/lib.macosx- 10.7-x86_64-3.6/ext.cpython-36m-darwin.so
>> python setup.py install
安装命令正常工作,但构建一个给出了 1 个警告。现在,当我尝试在我的 python 程序中 import ext 并使用函数 ext.cpu(integer_value) 时,程序给了我以下错误:
分段错误:11
知道可能导致问题的原因以及如何解决它吗?
【问题讨论】:
-
ncompatible pointer types passing 'PyMethodDef (*)[1]' to > parameter of type > 'struct PyModuleDef *'这是一个严重的警告。意味着底层代码将读取一个 pymodule 但你传递了一个 pymethod... -
@Jean-FrançoisFabre 我正在按照教程编写代码,所以我不知道如何实现这一点。请问你碰巧知道我该如何解决它吗?教程:youtube.com/watch?v=s6cvSkbWG3s
-
你需要阅读the actual docs。此外,虽然为了看看所有部分是什么而努力一次是值得的,除非你真的喜欢低级 C 编程,否则你应该认真考虑用 Cython 编写扩展,或者至少用稍微高级一点的语言可以为您自动化所有烦人的东西的库,例如带有 PyCxx、Boost 或 CPyExt 的 C++、带有 Pyd 的 D、带有 rust-python 的 Rust 等。不再需要处理难以调试的表、引用计数等问题。
-
另外,在某些情况下,使用普通旧 C API 编写 C 库会更容易,构建为普通旧 dylib/so/dll,然后使用
cffi或ctypes来从 Python 或 SWIG 之类的库中包装它以自动构建包装器。 -
@abarnert 我对这些东西完全陌生。曾是 C# 程序员,但现在来到 C 领域。最重要的是进行低级 C 编程的原因是访问硬件的每个性能计数器,因此构建 c 扩展程序以便能够从 python 程序中使用它(我肯定使用 python 比使用 C 更舒服)。无论如何,您认为我可以使用 Cython 进行如此低级的 C 编程吗?