标签: python-c-extension

在valgrind下运行python会显示许多内存错误,这是正常的吗?

我试图在我的Python C扩展中调试内存崩溃,并尝试在valgrind下运行脚本.我发现valgrind输出中有太多的"噪音",即使我运行简单的命令:

valgrind python -c ""
Run Code Online (Sandbox Code Playgroud)

Valgrind输出完整的重复信息,如下所示:

==12317== Invalid read of size 4
==12317==    at 0x409CF59: PyObject_Free (in /usr/lib/libpython2.5.so.1.0)
==12317==    by 0x405C7C7: PyGrammar_RemoveAccelerators (in /usr/lib/libpython2.5.so.1.0)
==12317==    by 0x410A1EC: Py_Finalize (in /usr/lib/libpython2.5.so.1.0)
==12317==    by 0x4114FD1: Py_Main (in /usr/lib/libpython2.5.so.1.0)
==12317==    by 0x8048591: main (in /usr/bin/python2.5)
==12317==  Address 0x43CD010 is 7,016 bytes inside a block of size 8,208 free'd
==12317==    at 0x4022F6C: free (in /usr/lib/valgrind/x86-linux/vgpreload_memcheck.so)
==12317==    by 0x4107ACC: PyArena_Free (in /usr/lib/libpython2.5.so.1.0)
==12317==    by 0x41095D7: PyRun_StringFlags (in /usr/lib/libpython2.5.so.1.0)
==12317==    by 0x40DF262: (within /usr/lib/libpython2.5.so.1.0)
==12317== …
Run Code Online (Sandbox Code Playgroud)

python debugging valgrind memory-leaks python-c-extension

17
推荐指数
2
解决办法
6516
查看次数

PyArg_ParseTupleAndKeywords如何工作?

我一直在努力学习如何为Python编写C扩展,并希望确定我理解PyArg_ParseTupleAndKeywords的工作原理.

我相信第一个参数是一个PyObject指针,它指向一个参数数组,这些参数按照它们传递的顺序传递给C-extension函数.第二个参数是传递的关键字列表,它们被传递的位置,以及非常可能的某种指示标记,告诉关键字开始和位置变得无关紧要.

然后,PyArg_ParseTupleAndKeywords使用其关键字列表(第四个参数)来映射用关键字指定的参数,以及格式字符串(第三个参数)和应该复制适当值的C变量(第五个和+参数)的地址.

我的理解是否正确?当我阅读在线文档时,我所看到的只是对"位置参数和关键字参数"的引用,这让我感到有些不知所措.处理PyArg_ParseTupleAndKeywords的Python解释器的文件在哪里?

python python-c-api python-c-extension

17
推荐指数
2
解决办法
6176
查看次数

为python包制作可选C扩展的最简单方法是什么?

我已经创建了一个C扩展,我想在我的Python包中启用(使用setuptools),只有传入命令行选项.最简单的方法是什么?

我似乎无法找到任何直截了当的方式来解决这个问题.

python setuptools cython python-c-extension

14
推荐指数
2
解决办法
1960
查看次数

具有可变数量参数的Python扩展模块

我试图找出在C扩展模块中如何为函数提供一个变量(也许是)相当多的参数.

阅读有关PyArg_ParseTuple的内容,您似乎必须知道要接受多少,一些是必需的,一些是可选的,但都有自己的变量.我希望PyArg_UnpackTuple能够处理这个问题,但是当我尝试以错误的方式使用它时,它似乎只会给我总线错误.

作为一个例子,将以下可能想要的python代码放入扩展模块(在C中).

def hypot(*vals):
    if len(vals) !=1 :
        return math.sqrt(sum((v ** 2 for v in vals)))
    else: 
        return math.sqrt(sum((v ** 2 for v in vals[0])))
Run Code Online (Sandbox Code Playgroud)

这可以用任何数量的参数调用或遍历,hypot(3,4,5),hypot([3,4,5]),并hypot(*[3,4,5])都给予了同样的答案.

我的C函数的开头看起来像这样

static PyObject *hypot_tb(PyObject *self, PyObject *args) {
// lots of code
// PyArg_ParseTuple or PyArg_UnpackTuple
}
Run Code Online (Sandbox Code Playgroud)

许多人认为是yasar11732.这里的下一个人是一个完全正常工作的扩展模块(_toolboxmodule.c),它只接受任何数字或整数参数,并返回由这些参数组成的列表(名称不好).一个玩具,但说明了需要做什么.

#include <Python.h>

int ParseArguments(long arr[],Py_ssize_t size, PyObject *args) {
    /* Get arbitrary number of positive numbers from Py_Tuple */
    Py_ssize_t i;
    PyObject *temp_p, …
Run Code Online (Sandbox Code Playgroud)

c python python-c-extension

13
推荐指数
1
解决办法
4926
查看次数

PyMODINIT_FUNC和PyModule_Create之间的区别

如果我理解正确,

  1. Python 2.X PyModule_Create中的PyMODINIT_FUNC 已被Python3.X 取代
  2. PyObject*然而,两者都返回Python 3.X,模块的初始化函数必须返回PyObject*模块 - 即

    PyMODINIT_FUNC
    PyInit_spam(void)
    {
       return PyModule_Create(&spammodule);
    }
    
    Run Code Online (Sandbox Code Playgroud)

    而在Python2.X中,这不是必要的 - 即

    PyMODINIT_FUNC
    initspam(void)
    {
      (void) Py_InitModule("spam", SpamMethods);
    }
    
    Run Code Online (Sandbox Code Playgroud)

所以,我的理智检查问题是:

  • 我的理解是否正确?
  • 为什么要做出这种改变?

现在,我只是在尝试非常简单的Python C扩展案例.也许如果我做得更多,那么答案就很明显,或者如果我试图将Python嵌入其他东西......

python python-c-extension python-3.x

13
推荐指数
1
解决办法
4982
查看次数

如何使用Cython类型的内存视图来接受Python中的字符串?

我如何编写一个Cython函数,它将一个字节串对象(一个普通字符串,一个bytearray或另一个跟在缓冲区协议下的对象)作为一个类型化的内存视图

根据Unicode和Passing Strings Cython教程页面,以下内容应该有效:

cpdef object printbuf(unsigned char[:] buf):
    chars = [chr(x) for x in buf]
    print repr(''.join(chars))
Run Code Online (Sandbox Code Playgroud)

它适用于bytearrays和其他可写缓冲区:

$ python -c 'import test; test.printbuf(bytearray("test\0ing"))'
'test\x00ing'
Run Code Online (Sandbox Code Playgroud)

但它不适用于普通字符串和其他只读缓冲区对象:

$ python -c 'import test; test.printbuf("test\0ing")'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "test.pyx", line 1, in test.printbuf (test.c:1417)
  File "stringsource", line 614, in View.MemoryView.memoryview_cwrapper (test.c:6795)
  File "stringsource", line 321, in View.MemoryView.memoryview.__cinit__ (test.c:3341)
BufferError: Object is not writable.
Run Code Online (Sandbox Code Playgroud)

查看生成的C代码,Cython总是将PyBUF_WRITABLE标志传递给PyObject_GetBuffer(),这解释了异常. …

python cython python-c-extension python-2.7 memoryview

13
推荐指数
2
解决办法
1835
查看次数

使用调试版本时,为C扩展处理"_d"后缀的最佳方法是什么?

我正在尝试调试Python 2.7的C扩展.我使用python2.7调试版本.我建立我的项目,setuptoolssetup.py有这样的台词:

ext_modules=[Extension("my.extension",
                       ["my/_extension.c"])]
Run Code Online (Sandbox Code Playgroud)

当我python setup.py install因某种原因调用扩展时编译为带_d后缀的文件,之后,在Python中,我不能这样做import my.extension,我只能这样做import my.extension_d.而我得到的是:

Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "build/bdist.linux-x86_64/egg/my/extension_d.py", line 7, in <module>
  File "build/bdist.linux-x86_64/egg/my/extension_d.py", line 6, in __bootstrap__
ImportError: dynamic module does not define init function (initextension_d)
Run Code Online (Sandbox Code Playgroud)

当然我的扩展没有initextension_d,它只有initextension功能.

这非常不方便,因为我必须更改一些代码并将此_d后缀添加到导入和其他内容中.

是否可以关闭此后缀的前置?或者如何以其他方式处理该问题?也许有一些"官方"的方式?

更新#0

我使用的是Ubuntu Linux.

python python-c-api python-c-extension

12
推荐指数
1
解决办法
664
查看次数

如何使用PIP编译带有调试信息的Python扩展

我有Python扩展的源代码.我想在调试时查看该扩展的调试符号.如何告诉PIP编译和链接我的扩展的调试符号?

(最好是平台不可知,否则Linux)

python-c-extension

12
推荐指数
1
解决办法
2815
查看次数

二进制上传后,easy_install因错误"无法找到设置脚本"而失败?

上传我的Python C扩展的二进制发行版后python setup.py bdist upload,easy_install [my-package-name]失败"错误:无法在/ tmp/easy_install/package-name-etc-etc中找到安装脚本".

我究竟做错了什么?

python binary easy-install python-c-extension

11
推荐指数
2
解决办法
2万
查看次数

将三维numpy数组传递给C.

我正在为我的Python程序编写一个C扩展用于速度目的,并且遇到一些非常奇怪的行为,试图传入一个三维的numpy数组.它适用于一个二维数组,但我确定我正在搞砸一些指针试图让它与第三维一起工作.但这是奇怪的部分.如果我只是传入一个三维数组,它会因总线错误而崩溃.如果(在Python中)我首先将我的变量创建为2D数组,然后用3D数组覆盖它,它可以完美地工作.如果变量首先是空数组,然后是3D数组,则会发生Seg Fault故障.怎么可能发生这种情况?

此外,任何人都可以帮助我获得3D阵列吗?或者我应该放弃并传递2D数组并自行重塑它?

这是我的C代码:

static PyObject* func(PyObject* self, PyObject* args) {
  PyObject *list2_obj;
  PyObject *list3_obj;
  if (!PyArg_ParseTuple(args, "OO", &list2_obj, &list3_obj))
    return NULL;

  double **list2;
  double ***list3;

  //Create C arrays from numpy objects:
  int typenum = NPY_DOUBLE;
  PyArray_Descr *descr;
  descr = PyArray_DescrFromType(typenum);
  npy_intp dims[3];
  if (PyArray_AsCArray(&list2_obj, (void **)&list2, dims, 2, descr) < 0 || PyArray_AsCArray(&list3_obj, (void ***)&list3, dims, 3, descr) < 0) {
    PyErr_SetString(PyExc_TypeError, "error converting to c array");
    return NULL;
  }
  printf("2D: %f, 3D: …
Run Code Online (Sandbox Code Playgroud)

c python pointers numpy python-c-extension

11
推荐指数
2
解决办法
6636
查看次数