标签: python-c-api

Python C扩展 - 接收dict作为参数

我正在写一个C扩展,我很失落如何接受一个dict作为参数.由于文档没有关于如何实现这一点的任何细节,我试图将参数解析为Python对象,然后将其作为dict操作:

PyTypeObject *dict;

if(!PyArg_ParseTuple(args, "o", &dict))
    return NULL;
Run Code Online (Sandbox Code Playgroud)

但代码在解析时失败:

Python 2.7.2 (default, Jun 20 2012, 16:23:33) 
[GCC 4.2.1 Compatible Apple Clang 4.0 (tags/Apple/clang-418.0.60)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import plotting
>>> plotting.plot({'wff':0})
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: must be impossible<bad format char>, not dict
Run Code Online (Sandbox Code Playgroud)

据我所知,从错误消息格式char是错误的(我认为"o"应代表任何Python对象).

将Python dict解析为C指针的最佳方法是什么?我正在挖掘文档,但我没有找到类似的东西.

谢谢.

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

4
推荐指数
1
解决办法
3583
查看次数

如何从 C API 返回包含 None 值的元组?

将包含None值的元组从 C 扩展返回到 Python的适当方法是什么?我知道None可以使用创建单个值

result = Py_BuildValue("");
Run Code Online (Sandbox Code Playgroud)

并且可以使用类似的东西创建元组

result = Py_BuildValue("(ii)", 123, 456);
Run Code Online (Sandbox Code Playgroud)

但我没有看到一种方法可以将它结合起来得到一个包含适当整数和None值的元组。

python python-c-api

4
推荐指数
1
解决办法
1517
查看次数

{tp_alloc, tp_dealloc} 和 {tp_new, tp_free} 应该被视为对吗?

在 tp_alloc 中创建的任何东西都应该在 tp_dealloc 中销毁是真的吗?{tp_new, tp_free} 也是如此?

它看起来像一个明显的对称,但我会很感激澄清。


我的实际用例是这样的:我有:

class OSClass : PyObject {...}

class Final : OSClass {...}
Run Code Online (Sandbox Code Playgroud)

所以对应的PyTypeObject pto有:

pto->tp_basicsize = sizeof(FinalClass)
pto->tp_dealloc = (destructor) 
                  [](PyObject* pyob) { PyMem_Free(pyob); };
Run Code Online (Sandbox Code Playgroud)

然而,新样式类将 PyObject 及其对应的 C++ 对象彼此分开存储,因此工作方式不同。

它在 tp_new 中创建 PyObject,在 tp_init 中创建相应的 C++ 对象。

并在 tp_dealloc 中销毁它们

这是正确的/最佳的吗?

代码:

// extra void* to point to corresponding C++ object
pto->tp_basicsize = sizeof(PyObject) + sizeof(void*)

pto->tp_new = new_func;
pto->tp_init = init_func;
pto->tp_dealloc = dealloc_func;

static PyObject* new_func( PyTypeObject* subtype, …
Run Code Online (Sandbox Code Playgroud)

c++ pycxx python-c-api

4
推荐指数
1
解决办法
1048
查看次数

Python 比较 C API 中的对象

给定两个PyObject*s,我如何在 C API 中比较它们?

我一开始想到a == b,但它显然是不正确的,因为它会比较指针而不是对象。我正在寻找a == b(不是a is b)Python C API 中的 Python 等价物。

c python python-c-api

4
推荐指数
1
解决办法
908
查看次数

编译多个模块时出现 Numpy/CAPI 错误,import_array()

我正在尝试编译一个 C++ 模块以使用它,scipy.weave该模块由几个头文件和源 C++ 文件组成。这些文件包含广泛使用 Numpy/C-API 接口的类和方法。但我无法弄清楚如何import_array()成功包含。过去一周我一直在为此苦苦挣扎,我快疯了。我希望你能帮助我,因为weave 帮助不是很解释。

在实践中,我首先调用pycapi_utils了一个模块,该模块包含一些将 C 对象与 Python 对象接口的例程。它由一个头文件pycapi_utils.h和一个源文件组成,pycapi_utils.cpp例如:

//pycapi_utils.h
#if ! defined _PYCAPI_UTILS_H
#define _PYCAPI_UTILS_H 1

#include <stdlib.h>
#include <Python.h>
#include <numpy/arrayobject.h>
#include <tuple>
#include <list>

typedef std::tuple<const char*,PyObject*> pykeyval; //Tuple type (string,Pyobj*) as dictionary entry (key,val)
typedef std::list<pykeyval> kvlist;                    

//Declaration of methods
PyObject* array_double_to_pyobj(double* v_c, long int NUMEL); //Convert from array to Python list (double)
...
...
#endif
Run Code Online (Sandbox Code Playgroud)

//pycapi_utils.cpp

#include "pycapi_utils.h" …
Run Code Online (Sandbox Code Playgroud)

c c++ python numpy python-c-api

4
推荐指数
1
解决办法
6370
查看次数

如何从 C 的 PyObject 类型的函数将值从 C 返回到 python?

我试图通过从 python 调用 C 文件来传递一个值,然后再次将该值从 C 返回到 python。

我的问题是如何做到这一点?可以使用返回Py_BuildValue(a+b)类型的东西吗?

#include <Python.h>

static PyObject *
hello_world(PyObject *self, PyObject *noargs)
{
   int a=5,b=10;

   return Py_BuildValue(a+b); //This is Errorus.
}


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



PyMODINIT_FUNC
inittesty2(void)
{
    Py_InitModule("testy2", module_functions);
}
Run Code Online (Sandbox Code Playgroud)

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

4
推荐指数
1
解决办法
2164
查看次数

Python CApi 引用计数详细信息

我在这里查看一些示例代码(https://docs.python.org/2.0/api/refcountDetails.html)并试图更好地理解两个示例之间的差异:第一个示例是:

PyObject *t;

t = PyTuple_New(3);
PyTuple_SetItem(t, 0, PyInt_FromLong(1L));
PyTuple_SetItem(t, 1, PyInt_FromLong(2L));
PyTuple_SetItem(t, 2, PyString_FromString("three"));
Run Code Online (Sandbox Code Playgroud)

作者解释说 PyTuple_SetItem()窃取了引用(因此无需 DECREF)。 好吧,我明白了。然后作者使用 PySequence_SetItem() 提供了类似的代码,它不会窃取引用,因此调用者必须 DECREF,示例代码如下所示:

PyObject *l, *x;

l = PyList_New(3);
x = PyInt_FromLong(1L);
PySequence_SetItem(l, 0, x); Py_DECREF(x);
x = PyInt_FromLong(2L);
PySequence_SetItem(l, 1, x); Py_DECREF(x);
x = PyString_FromString("three");
PySequence_SetItem(l, 2, x); Py_DECREF(x);
PyObject *l, *x;
Run Code Online (Sandbox Code Playgroud)

我的问题是,如果第二个示例与第一个示例类似,传递 PyTYPE_FromSOMETYPE 如下,会发生什么?

PyObject *l;

l = PyList_New(3);
PySequence_SetItem(l, 0, PyInt_FromLong(1L));
PySequence_SetItem(l, 1, PyInt_FromLong(2L));
PySequence_SetItem(l, 2, PyString_FromString("three"));
Run Code Online (Sandbox Code Playgroud)

最后一种情况是良性的,还是会导致内存泄漏(因为 PySequence_SetItem 不会取得 PyInt_FromLong …

python reference-counting python-c-api

4
推荐指数
1
解决办法
903
查看次数

使用调试 Python 安装在 Windows 上构建 Python-C-Extension

如果我在 Windows 上从源代码构建 CPython,当我想要 pip 安装包含 C 扩展的包时,我会遇到问题。链接库时似乎发生了错误。

例如,安装 cython 时(但在其他 C 扩展包上也会崩溃并出现相同的错误):

链接:致命错误 LNK1104:无法打开文件“python38.lib”

错误:命令“C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\MSVC\14.23.28105\bin\HostX86\x86\link.exe”失败,退出状态为 1104

之所以无法打开“python38.lib”,是因为调试模式下的“.lib”文件名为“python38_d.lib”。

一个最小的可重现示例(在命令行上)基于CPython 开发人员指南的快速参考

git clone --branch v3.8.0 https://github.com/python/cpython.git
cd cpython
git checkout v3.8.0
.\PCbuild\build.bat -e -d
.\PCbuild\win32\python_d.exe -m ensurepip
.\PCbuild\win32\python_d.exe -m pip install pip --upgrade -vv
.\PCbuild\win32\python_d.exe -m pip install setuptools --upgrade -vv
.\PCbuild\win32\python_d.exe -m pip install cython -vv
Run Code Online (Sandbox Code Playgroud)

结果distutils.sysconfig.get_config_vars()是:

{'BINDIR': '...\\cpython\\PCbuild\\win32',
 'BINLIBDEST': ...\\cpython\\Lib',
 'EXE': '.exe',
 'EXT_SUFFIX': '_d.cp38-win32.pyd',
 'INCLUDEPY': '...\\cpython\\include;...\\cpython\\PC',
 'LIBDEST': '...\\cpython\\Lib',
 'SO': '_d.cp38-win32.pyd',
 'VERSION': …
Run Code Online (Sandbox Code Playgroud)

python cpython pip setuptools python-c-api

4
推荐指数
1
解决办法
3764
查看次数

Python C API不加载模块

我正在尝试使用C API加载一个包含C中的数学和numpy导入的python模块.我可以加载并运行模块但是,如果我导入数学模块它不起作用.

我使用的是Arch Linux,Python 2.7.2和gcc.

这里的代码:

#include <stdio.h>
#include <stdlib.h>
#include <python2.7/Python.h>


int main(int argc, char **argv)
{
    PyObject *pName, *pModule, *pFunc, *pArg, *pDict, *pReturn, *pT1, *pT2, *pX, *pY;
    int i;
    double x, y;

    Py_Initialize();

    PySys_SetPath(".");

    pName = PyString_FromString("func");
    if (!pName)
    {
        printf("pName\n");
        return 0;
    }
    pModule = PyImport_Import(pName);

    pDict = PyModule_GetDict(pModule);
    pFunc = PyDict_GetItemString(pDict, "get_vals");
    pArg = PyTuple_New(2);
    PyTuple_SetItem(pArg, 0, PyFloat_FromDouble(4.0));
    PyTuple_SetItem(pArg, 1, PyFloat_FromDouble(2.0));
    pReturn = PyObject_CallObject(pFunc, pArg);
    pT1 = PyTuple_GetItem(pReturn, 0);
    pT2 = PyTuple_GetItem(pReturn, 1);

    for (i = …
Run Code Online (Sandbox Code Playgroud)

c python python-embedding python-c-api

3
推荐指数
1
解决办法
3947
查看次数

调用PyRun_String(...)返回NULL后,如何获取异常信息?

我正在尝试运行以下代码:

Py_Initialize();
PyObject *py_main = PyImport_AddModule("__main__");
PyObject *py_dict = PyModule_GetDict(py_main);
PyObject *ret = PyRun_String(SOME_PYTHON_CODE, Py_file_input, py_dict, py_dict);
Run Code Online (Sandbox Code Playgroud)

但似乎有在我的生成Python代码(一个错误的地方SOME_PYTHON_CODE)等ret出来作为NULL指示异常发生。如何获得此例外?

c python python-c-api

3
推荐指数
1
解决办法
1117
查看次数