我正在查看hasattr内置函数的源代码,并注意到一些引起我兴趣的行:
Py_INCREF(Py_False);
return Py_False;
...
Py_INCREF(Py_True);
return Py_True;
Run Code Online (Sandbox Code Playgroud)
不是Py_False和Py_True全球价值观?出于纯粹的好奇心,为什么Python保留这些变量的引用计数?
我在C中编写了一个Python扩展,它需要CoreFoundation框架(以及其他内容).这编译好:
gcc -o foo foo.c -framework CoreFoundation -framework Python
Run Code Online (Sandbox Code Playgroud)
("-framework"是一个仅限Apple的gcc扩展,但这没关系因为我正在使用他们的特定框架)
如何告诉setup.py将此标志传递给gcc?
我试过这个,但它似乎不起作用(它编译,但当我尝试运行它时抱怨未定义的符号):
from distutils.core import setup, Extension
setup(name='foo',
version='1.0',
author='Me',
ext_modules=[Extension('foo',
['foo.c'],
extra_compile_args=['-framework CoreFoundation'])])
Run Code Online (Sandbox Code Playgroud)
编辑:
这似乎有效:
from distutils.core import setup, Extension
setup(name='foo',
version='1.0',
author='Me',
ext_modules=[Extension('foo',
['foo.c'],
extra_link_args=['-framework', 'CoreFoundation'])])
Run Code Online (Sandbox Code Playgroud) 基本上似乎存在大量混淆/模糊性,而不PyEval_InitThreads()应该在什么时候被调用,以及需要哪些API调用.遗憾的是,官方Python文档非常模糊.关于这个主题的stackoverflow已经有很多问题了,事实上,我个人已经问了一个与这个问题几乎完全相同的问题,所以如果这个问题以复制方式结束,我不会特别感到惊讶; 但是考虑到这个问题似乎没有明确的答案.(可悲的是,我没有Guido Van Rossum的快速拨号.)
首先,让我们在这里定义问题的范围:我想做什么? 嗯...我想在C中编写一个Python扩展模块,它将:
pthread在C中使用API的Spawn工作线程好的,让我们从Python文档开始吧.在Python的3.2文档说:
void PyEval_InitThreads()
初始化并获取全局解释器锁.它应该在创建第二个线程或参与任何其他线程操作(如PyEval_ReleaseThread(tstate))之前在主线程中调用.在调用PyEval_SaveThread()或PyEval_RestoreThread()之前不需要它.
所以我的理解是:
PyEval_InitThreads()在生成任何其他线程之前从主线程调用
PyEval_InitThreads锁定GIL所以常识告诉我们,任何创建线程的C扩展模块都必须调用PyEval_InitThreads(),然后释放Global Interpreter Lock.好吧,看起来很简单.所以初步,所有的需要将以下代码:
PyEval_InitThreads(); /* initialize threading and acquire GIL */
PyEval_ReleaseLock(); /* Release GIL */
Run Code Online (Sandbox Code Playgroud)
看起来很简单......但不幸的是,Python 3.2文档也说PyEval_ReleaseLock已经弃用了.相反,我们应该使用PyEval_SaveThread以释放GIL:
PyThreadState*PyEval_SaveThread()
释放全局解释器锁(如果已创建并启用了线程支持)并将线程状态重置为NULL,则返回先前的线程状态(不是NULL).如果已创建锁,则当前线程必须已获取它.
呃......好吧,我想C扩展模块需要说:
PyEval_InitThreads();
PyThreadState* st = PyEval_SaveThread();
Run Code Online (Sandbox Code Playgroud)
实际上,这正是这个stackoverflow回答所说的.除非我在实践中尝试这样做,否则当我导入扩展模块时,Python解释器会立即出现错误.尼斯. …
python python-c-api python-c-extension python-3.x python-3.2
我正在使用Python的C API,但很难理解一些极端情况.我可以测试它,但它似乎容易出错并且耗费时间.所以我来这里看看有人已经这样做了.
问题是,哪个是使用子解释器管理多线程的正确方法,线程和子解释器之间没有直接关系?
Py_Initialize();
PyEval_InitThreads(); /* <-- needed? */
_main = PyEval_SaveThread(); /* <-- acquire lock? does it matter? */
/* maybe do I not need it? */
i1 = Py_NewInterpreter();
i2 = Py_NewInterpreter();
Run Code Online (Sandbox Code Playgroud)
我是否使用互斥锁?是否需要使用锁?线程函数应该类似于以下内容:(线程是非python,可能是POSIX线程)
线程1
_save = PyThreadState_Swap(i1);
// python work
PyThreadState_Restore(_save);
Run Code Online (Sandbox Code Playgroud)
Thread2(几乎相同)
_save = PyThreadState_Swap(i1);
// python work
PyThreadState_Restore(_save);
Run Code Online (Sandbox Code Playgroud)
Thread3(几乎相同,但与子解释器i2)
_save = PyThreadState_Swap(i2);
// python work
PyThreadState_Restore(_save);
Run Code Online (Sandbox Code Playgroud)
它是否正确?这是我想要实现的一般情况吗?有竞争条件吗?
谢谢!
我一直在努力学习如何为Python编写C扩展,并希望确定我理解PyArg_ParseTupleAndKeywords的工作原理.
我相信第一个参数是一个PyObject指针,它指向一个参数数组,这些参数按照它们传递的顺序传递给C-extension函数.第二个参数是传递的关键字列表,它们被传递的位置,以及非常可能的某种指示标记,告诉关键字开始和位置变得无关紧要.
然后,PyArg_ParseTupleAndKeywords使用其关键字列表(第四个参数)来映射用关键字指定的参数,以及格式字符串(第三个参数)和应该复制适当值的C变量(第五个和+参数)的地址.
我的理解是否正确?当我阅读在线文档时,我所看到的只是对"位置参数和关键字参数"的引用,这让我感到有些不知所措.处理PyArg_ParseTupleAndKeywords的Python解释器的文件在哪里?
我在Eigen Library的帮助下用C++做一些计算,函数是这样的:
MatrixXd Cov(MatrixXd Data)
{
VectorXd meanVector;
...
return Covariance;
}
Run Code Online (Sandbox Code Playgroud)
..在wrap python函数中:
static PyObject *Wrap_Cov(PyObject *self,PyObject *args)
{
Pyobject *Objectdata;
if(!PyArg_ParseTuple(args,"O", &ObjectData))
return NULL;
Cov(ObjectData);
return Py_BuildValue("O",&covariance_answer);
}
Run Code Online (Sandbox Code Playgroud)
显然,Python不知道我定义的''对象'',它不能将''MatrixXd''转换为''对象'',我认为它是某种''数组'',而不是''对象' "
如何在不使用boost的情况下执行此操作?
我试图从C++调用python类中的方法.调用它的C++方法是C++回调.
在我尝试调用python方法时,在这个方法中,它正在给予segmentation fault.
我已经在一个全局变量中保存了一个python函数实例
// (pFunc is global variable of type PyObject*)
pFunc = PyDict_GetItemString(pDict, "PlxMsgWrapper");
Run Code Online (Sandbox Code Playgroud)
其中PlxMsgWrapper是一个python方法,将在回调中使用.
在回调中,参数创建为
PyObject* args = PyTuple_Pack(2, PyString_FromString(header.c_str()),
PyString_FromString(payload.c_str()));
Run Code Online (Sandbox Code Playgroud)
在创建时
PyObject * pInstance = PyObject_CallObject(pFunc, args);
Run Code Online (Sandbox Code Playgroud)
在这一行中它给出了分段错误.在此之后,实际的python方法被称为
PyObject* recv_msg_func = PyObject_GetAttrString(module, (char *)"recvCallback");
args = PyTuple_Pack(1, pInstance);
PyObject_CallObject(recv_msg_func, args);
Run Code Online (Sandbox Code Playgroud) Python C API函数PyEval_EvalCode允许您执行已编译的Python代码.我想执行一段Python代码,就像它在函数范围内执行一样,因此它有自己的局部变量字典,不会影响全局状态.
这看起来很容易,因为PyEval_EvalCode您可以提供全局和本地词典:
PyObject* PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
我遇到的问题与Python如何查找变量名称有关.考虑以下代码,我执行PyEval_EvalCode:
myvar = 300
def func():
return myvar
func()
Run Code Online (Sandbox Code Playgroud)
这个简单的代码实际上会引发错误,因为Python无法myvar从内部找到变量func.即使myvar在外部作用域中的本地字典中,Python也不会将其复制到内部作用域中的本地字典中.原因如下:
每当Python查找变量名时,首先检查locals,然后检查globals,最后检查builtins.在模块范围,locals并且globals是SAME字典对象.因此,声明x = 5在模块范围内将放置x在该locals字典,这也是globals字典.现在,在函数范围内x找不到需要查找的模块作用域定义x的函数locals,因为Python不会将模块作用域本地复制到函数作用域本地.但是,这通常是没有问题的,因为它可以找到x在globals.
x = 5
def foo():
print(x) # This works because 'x' in …Run Code Online (Sandbox Code Playgroud) 我正在阅读python中定义'新类型'的教程, https://docs.python.org/2/extending/newtypes.html,我不明白在这段代码中使用Py_DECREF的目的.
static PyObject *
Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
Noddy *self;
self = (Noddy *)type->tp_alloc(type, 0);
if (self != NULL) {
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
self->last = PyString_FromString("");
if (self->last == NULL)
{
Py_DECREF(self);
return NULL;
}
self->number = 0;
}
return (PyObject *)self;
}
Run Code Online (Sandbox Code Playgroud)
我对引用计数的理解是不完整的,任何帮助都将受到赞赏.
我正在开发一个 Python C 扩展,我想公开一个完全在 C 中定义的自定义枚举(如:继承自 enum.Enum 的类)。
事实证明这不是一个微不足道的任务,并且继承使用的常规机制.tp_base不起作用 - 很可能是由于 Enum 的元类没有被引入。
基本上我正在尝试这样做:
import enum
class FooBar(enum.Enum):
FOO = 1
BAR = 2
Run Code Online (Sandbox Code Playgroud)
在C.
经过大量深入研究 cpython 的内部结构后,这就是我想到的,包装在一个示例可构建模块中:
#include <Python.h>
PyDoc_STRVAR(module_doc,
"C extension module defining a class inheriting from enum.Enum.");
static PyModuleDef module_def = {
PyModuleDef_HEAD_INIT,
.m_name = "pycenum",
.m_doc = module_doc,
.m_size = -1,
};
struct enum_descr {
const char *name;
long value;
};
static const struct enum_descr foobar_descr[] = {
{
.name = "FOO",
.value = …Run Code Online (Sandbox Code Playgroud) python ×10
python-c-api ×10
c ×3
python-3.x ×3
c++ ×2
callback ×1
cpython ×1
distutils ×1
eigen ×1
matrix ×1
python-3.2 ×1