标签: python-c-extension

有没有理由在PyMem_Malloc上使用malloc?

我正在阅读Python C扩展中的内存管理文档,据我所知,似乎没有太多理由使用malloc而不是PyMem_Malloc.假设我想分配一个不暴露给Python源代码的数组,并将存储在一个将被垃圾收集的对象中.有什么理由可以使用malloc吗?

c python malloc python-c-extension

8
推荐指数
2
解决办法
3878
查看次数

从C返回对象到Python

我已经阅读了Python C-API的文档,甚至还编写了一些扩展模块.但是,在从C函数返回Python对象时,我仍然有点不清楚它的确切语义.

Python文档中的有限示例通常显示一个返回结果的C函数Py_BuildValue.现在,Py_BuildValue返回a New Reference,并将此引用的所有权转移给解释器.那么,我可以从中推断出一般规则是返回Python的任何对象必须是新引用,并且从C函数返回对象与将对象的所有权转移到解释器相同吗?

如果是这样,那么返回已经拥有某个东西的对象的情况又如何呢?例如,假设你编写一个C函数,它接受a PyObject*是a tuple,然后调用PyTuple_GetItem它并返回结果. PyTuple_GetItem返回一个借来的引用 - 意味着该项仍然由元组"拥有".那么,在将函数返回给解释器之前,返回结果的C函数PyTuple_GetItem是否有INCREF结果?

例如:

static PyObject* my_extension_module(PyObject* tup)
{
   PyObject* item = PyTuple_GetItem(tup, 1);
   if (!item) { /* handle error */ }

   return item; // <--- DO WE NEED TO INCREF BEFORE RETURNING HERE?
}
Run Code Online (Sandbox Code Playgroud)

c python python-c-api python-c-extension

8
推荐指数
1
解决办法
1720
查看次数

如何为不同的OS/Python版本编译Python C/C++扩展?

我注意到几个成熟的Python库都有针对大多数架构(Win32/Win-amd64/MacOS)和Python版本的预编译版本.针对不同环境交叉编译扩展的标准方法是什么?葡萄酒?虚拟机?人群采购?

python packaging cross-platform python-c-extension

8
推荐指数
2
解决办法
1818
查看次数

在C中嵌入Python,链接失败,未定义引用`Py_Initialize'

我正在尝试从文档https://docs.python.org/2.7/extending/embedding.html编译示例,我的代码看起来与5.1下的代码完全相同:

#include <Python.h>

int
main(int argc, char *argv[])
{
  Py_SetProgramName(argv[0]);
  Py_Initialize();
  PyRun_SimpleString("from time import time, ctime\n"
                     "print 'Today is', ctime(time())\n");

  Py_Finalize();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我使用以下命令编译它,它对我来说很好,并给我所需的目标文件:

gcc -c $(python2.7-config --cflags) embedpy.c
Run Code Online (Sandbox Code Playgroud)

要链接它,我使用以下命令,最终出现以下错误:

gcc $(/usr/bin/python2.7-config --ldflags) embedpy.o
embedpy.o: In function `main':
/home/miguellissimo/embedpy.c:6: undefined reference to `Py_SetProgramName'
/home/miguellissimo/embedpy.c:7: undefined reference to `Py_Initialize'
/home/miguellissimo/embedpy.c:8: undefined reference to `PyRun_SimpleStringFlags'
/home/miguellissimo/embedpy.c:11: undefined reference to `Py_Finalize'
collect2: error: ld returned 1 exit status
Run Code Online (Sandbox Code Playgroud)

我无法找出我做错了什么,或者我忘了让这个例子工作.

PS:python2.7-config命令在我的Xubuntu机器上提供以下输出:

>>> python2.7-config --cflags 
-I/usr/include/python2.7 -I/usr/include/x86_64-linux-gnu/python2.7  -fno-stri
ct-aliasing -D_FORTIFY_SOURCE=2 -g -fstack-protector …
Run Code Online (Sandbox Code Playgroud)

c python python-c-extension

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

如何在Cython中创建固定长度,可变的Python对象数组?

我需要有一个python对象数组用于创建一个trie数据结构.我需要一个像元组一样固定长度的结构,像列表一样可变.我不想用一个列表,因为我希望能够确保该列表是正好合适的大小(如果它开始分配额外的元素,内存开销很可能会迅速增加为线索变大).有没有办法做到这一点?我尝试创建一个对象数组:

cdef class TrieNode:
    cdef object members[32]
Run Code Online (Sandbox Code Playgroud)

......但是这给了一个错误:

Error compiling Cython file:
------------------------------------------------------------
...
cdef class TrieNode:
    cdef object members[32]
                      ^
------------------------------------------------------------

/Users/jason/src/pysistence/source/pysistence/trie.pyx:2:23: Array element cannot be a Python object
Run Code Online (Sandbox Code Playgroud)

做我想做的最好的方法是什么?

python arrays trie cython python-c-extension

7
推荐指数
2
解决办法
2325
查看次数

Python C API:使用PyEval_EvalCode

我正试图弄清楚如何使用C语言的Python解释器,我遇到了麻烦PyEval_EvalCode.基本上,我正在编写一个C函数,它接受任意Python代码串,编译它,执行它,然后打印出结果.

问题在于,当我打印出结果时,我总是得到None,即使表达式显然没有评估None.

这是代码(为清楚起见,删除了错误检查和引用计数):

void eval(const char* s)
{
    PyCodeObject* code = (PyCodeObject*) Py_CompileString(s, "test", Py_file_input);
    PyObject* main_module = PyImport_AddModule("__main__");
    PyObject* global_dict = PyModule_GetDict(main_module);
    PyObject* local_dict = PyDict_New();
    PyObject* obj = PyEval_EvalCode(code, global_dict, local_dict);

    PyObject* result = PyObject_Str(obj);
    PyObject_Print(result, stdout, 0);
}
Run Code Online (Sandbox Code Playgroud)

我尝试将此函数"5 + 5"作为输入调用,并显示None.我使用PyEval_EvalCode不正确吗?

python python-c-api python-c-extension python-3.x

7
推荐指数
1
解决办法
4820
查看次数

Python C Extensions - 为什么必须可调用的C函数接受参数并返回PyObject*

我刚刚开始使用Python C扩展,并且很好奇为什么可以从Python调用的C函数必须使用2个PyObject*参数并返回PyObject*.我写了以下"Hello World"扩展:

#include <Python.h>

static PyObject *
hello_world(PyObject *self, PyObject *noargs)
{
   printf("Hello World\n");
   return Py_BuildValue("");
}


// Module functions table.

static PyMethodDef
module_functions[] = {
    { "hello_world", hello_world, METH_NOARGS, "hello world method" },
    { NULL }
};


// This function is called to initialize the module.
PyMODINIT_FUNC
inittesty2(void)
{
    Py_InitModule("testy2", module_functions);
}
Run Code Online (Sandbox Code Playgroud)

为什么我(特别是使用METH_NOARGS)不能使用以下hello_world方法:

static void
hello_world()
{
   printf("Hello World\n");
}
Run Code Online (Sandbox Code Playgroud)

c python python-c-extension

7
推荐指数
1
解决办法
2418
查看次数

Python C扩展 - 为什么使用关键字参数的方法强制转换为PyCFunction

我正在学习Python-C扩展,并且很困惑为什么使用关键字参数的方法必须强制转换为PyCFunctions.

我对PyCFunction的理解是它需要两个指向PyObjects的指针并返回一个指向PyObject的指针 - 例如

 PyObject* myFunc(PyObject* self, PyObject* args)
Run Code Online (Sandbox Code Playgroud)

如果我要使用一个使用关键字参数的函数,那么这个函数将使用三个指向PyObjects的指针并返回一个指向PyObject的指针 - 例如

 PyObject* myFunc(PyObject* self, PyObject* args, PyObject* keywordArgs)
Run Code Online (Sandbox Code Playgroud)

但是,当我创建模块函数数组时(对于一个名为'adder'的函数):

{ "adder", (PyCFunction)adder, METH_VARARGS | METH_KEYWORDS, "adder method" }
Run Code Online (Sandbox Code Playgroud)

工作良好.感觉就像我将一个浮点数转换为int并仍然使用浮点数的非整数部分.如果我没有看到这项工作,我会认为它不会起作用.我在这里不理解什么?

此外,我看到一些PyCFunctionWithKeywords的引用,它似乎有我认为我需要的函数签名,但我的编译器抱怨(发出警告)'不兼容的指针类型'.

是不是弃用了PyCFunctionWithKeywords?如果没有,是否有时间我应该/必须使用它?

python python-c-extension

7
推荐指数
1
解决办法
1934
查看次数

Python-C集成:Ctypes,CFFI或创建二进制模块

基本上我想用C编写的Python程序调用函数.

所以(据我所知)我的选择是:

  • CTypes/CFFI
    • 创建包含C函数的DLL/SO/DyLib,并使用CTypes或CFFI访问它们.显然CFFI更快,唯一的缺点是必须在python中声明所有函数签名.
    • 优点:
      • 不必在我的C函数中进行任何调整.所有类型转换都是在Python中完成的.
    • 缺点:
      • 表现?
  • Python二进制模块
    • 在C中编写一个python接口,将我的C模块转换为二进制python模块
    • 优点:
      • 表现?
    • 缺点:
      • 所有类型转换都在C语言中完成.使用[SIP] [3]这可能是自动化的.

将C模块转换为python二进制模块真的更快吗?

两个解决方案是否都支持向C函数发送python回调?

SIP是生成python接口的好选择吗?还有其他选择吗?

其中任何一个都有其他特殊性吗?

c python python-c-extension python-sip python-cffi

7
推荐指数
1
解决办法
3762
查看次数

python c-api:使用现有缓冲区创建字节而不复制

在我看来,缓冲区协议更像是将 Python 缓冲区暴露给 C。

我找不到使用现有缓冲区创建字节对象的方法,而无需在 C 中进行复制。

基本上我想要的是实现类似于 PyBytes_FromStringAndSize() 但不复制的东西,并在对象被释放时使用回调来释放缓冲区。在收到从 C API 返回的缓冲区之前,我不知道缓冲区有多大。所以先在 Python 中创建 bytes 对象然后再填充它不是一种选择。

我还查看了 memoryview,PyMemoryView_FromMemory() 不会复制,但无法通过回调来释放我的缓冲区。而且我不是 suse Python lib(例如 Psycopg)是否可以使用 memoryview 对象。

我是否必须创建自己的对象才能实现这两个要求?还有什么捷径吗?

如果必须,我如何确保这个对象与字节一样工作,以便我可以安全地将它传递给 Python lib?

谢谢。

python-c-api python-c-extension python-3.x

7
推荐指数
1
解决办法
376
查看次数