标签: python-c-api

为什么Python将引用计数保持为False和True?

我正在查看hasattr内置函数的源代码,并注意到一些引起我兴趣的行:

Py_INCREF(Py_False);
return Py_False;

...

Py_INCREF(Py_True);
return Py_True;
Run Code Online (Sandbox Code Playgroud)

不是Py_FalsePy_True全球价值观?出于纯粹的好奇心,为什么Python保留这些变量的引用计数?

python reference-counting python-c-api

21
推荐指数
1
解决办法
1608
查看次数

如何在Python setup.py脚本中将标志传递给gcc?

我在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)

python distutils python-c-api

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

Python 3中的PyEval_InitThreads:如何/何时调用它?(传奇继续令人作呕)

基本上似乎存在大量混淆/模糊性,而不PyEval_InitThreads()应该在什么时候被调用,以及需要哪些API调用.遗憾的是,官方Python文档非常模糊.关于这个主题的stackoverflow已经有很多问题了,事实上,我个人已经问了一个与这个问题几乎完全相同的问题,所以如果这个问题以复制方式结束,我不会特别感到惊讶; 但是考虑到这个问题似乎没有明确的答案.(可悲的是,我没有Guido Van Rossum的快速拨号.)

首先,让我们在这里定义问题的范围:我想做什么? 嗯...我想在C中编写一个Python扩展模块,它将:

  1. pthread在C中使用API的Spawn工作线程
  2. 从这些C线程中调用Python回调

好的,让我们从Python文档开始吧.在Python的3.2文档说:

void PyEval_InitThreads()

初始化并获取全局解释器锁.它应该在创建第二个线程或参与任何其他线程操作(如PyEval_ReleaseThread(tstate))之前在主线程中调用.在调用PyEval_SaveThread()或PyEval_RestoreThread()之前不需要它.

所以我的理解是:

  1. 产生线程的任何C扩展模块必须PyEval_InitThreads()在生成任何其他线程之前从主线程调用
  2. 调用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

20
推荐指数
3
解决办法
6203
查看次数

Python多线程多解释器C API

我正在使用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 multithreading python-c-api

20
推荐指数
1
解决办法
4704
查看次数

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中使用Eigen Library函数调用C++

我在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 matrix python-c-api eigen

15
推荐指数
1
解决办法
3193
查看次数

从C++(或C)回调中调用python方法

我试图从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)

c c++ python callback python-c-api

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

C Python:在上下文中运行Python代码

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不会将模块作用域本地复制到函数作用域本地.但是,这通常是没有问题的,因为它可以找到xglobals.

x = 5
def foo():
   print(x) # This works because 'x' in …
Run Code Online (Sandbox Code Playgroud)

c python cpython python-c-api python-3.x

14
推荐指数
1
解决办法
1647
查看次数

Py_DECREF和PY_INCREF的目的是什么?

我正在阅读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 python-c-api

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

在 C 扩展中定义 Python 枚举 - 我这样做对吗?

我正在开发一个 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)

c python python-c-api python-3.x python-extensions

14
推荐指数
1
解决办法
638
查看次数