我正在阅读Python C扩展中的内存管理文档,据我所知,似乎没有太多理由使用malloc而不是PyMem_Malloc.假设我想分配一个不暴露给Python源代码的数组,并将存储在一个将被垃圾收集的对象中.有什么理由可以使用malloc吗?
我已经阅读了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) 我注意到几个成熟的Python库都有针对大多数架构(Win32/Win-amd64/MacOS)和Python版本的预编译版本.针对不同环境交叉编译扩展的标准方法是什么?葡萄酒?虚拟机?人群采购?
我正在尝试从文档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) 我需要有一个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)
做我想做的最好的方法是什么?
我正试图弄清楚如何使用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 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)
?
我正在学习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?如果没有,是否有时间我应该/必须使用它?
基本上我想用C编写的Python程序调用函数.
所以(据我所知)我的选择是:
将C模块转换为python二进制模块真的更快吗?
两个解决方案是否都支持向C函数发送python回调?
SIP是生成python接口的好选择吗?还有其他选择吗?
其中任何一个都有其他特殊性吗?
在我看来,缓冲区协议更像是将 Python 缓冲区暴露给 C。
我找不到使用现有缓冲区创建字节对象的方法,而无需在 C 中进行复制。
基本上我想要的是实现类似于 PyBytes_FromStringAndSize() 但不复制的东西,并在对象被释放时使用回调来释放缓冲区。在收到从 C API 返回的缓冲区之前,我不知道缓冲区有多大。所以先在 Python 中创建 bytes 对象然后再填充它不是一种选择。
我还查看了 memoryview,PyMemoryView_FromMemory() 不会复制,但无法通过回调来释放我的缓冲区。而且我不是 suse Python lib(例如 Psycopg)是否可以使用 memoryview 对象。
我是否必须创建自己的对象才能实现这两个要求?还有什么捷径吗?
如果必须,我如何确保这个对象与字节一样工作,以便我可以安全地将它传递给 Python lib?
谢谢。
python ×9
c ×5
python-c-api ×3
python-3.x ×2
arrays ×1
cython ×1
malloc ×1
packaging ×1
python-cffi ×1
python-sip ×1
trie ×1