标签: python-c-api

通过 C API 创建新的 numpy 标量并实现自定义视图

简洁版本

给定一个内置的四元数数据类型,如何将四元数的 numpy 数组视为具有大小为 4 的额外维度的浮点数 numpy 数组(不复制内存)?

长版

Numpy 内置了对浮点数和复杂浮点数的支持。我需要使用四元数——它概括了复数,但它们不是有两个分量,而是有四个分量。已经有一个非常好的包,它使用 C API 将四元数直接合并到 numpy 中,它似乎可以非常快地完成所有操作。我还需要添加一些四元数函数,但我想我基本上可以处理这些。

但是,我还希望能够在我需要使用 Awesomenumba包编写的其他函数中使用这些四元数。不幸的是,numba 目前无法处理自定义类型。但我不需要那些 numba 函数中的奇特四元数函数;我只需要数字本身。所以我希望能够将四元数数组重新转换为具有一个额外维度(大小为 4)的浮点数数组。特别是,我想只使用数组中已有的数据而不进行复制,并将其视为新数组。我找到了PyArray_View函数,但不知道如何实现它。

(我非常有信心数据连续保存在内存中,我认为这是简单查看它们所必需的。具体来说,elsize = 8*4alignment = 8四元数包中。)

python numpy python-c-api

5
推荐指数
1
解决办法
210
查看次数

使用Python3 C API添加到内置函数

我正在寻找使用 Python3 C API 来添加内置函数。我这样做只是为了帮助我熟悉 Python C API 的练习。这个问题的答案很好地解释了为什么人们可能不想这样做。无论如何,我想foo向Pythonbuiltins模块添加一个函数。

这是我到目前为止所做的( foo.c):

#include <Python.h>
#include <stdio.h>

static PyObject*
foo(PyObject *self, PyObject *args){
    printf("foo called");
    return Py_None;
}

char builtin_name[] = "builtins";
char foo_name[] = "foo";
char foo_doc[] = "foo function";

static PyMethodDef foo_method = {foo_name, foo, METH_NOARGS, foo_doc};

PyMODINIT_FUNC
PyInit_foo(void){
    PyObject *builtin_module = PyImport_ImportModule(builtin_name);
    PyModule_AddFunctions(builtin_module, &foo_method);
    return builtin_module;
}
Run Code Online (Sandbox Code Playgroud)

我将其放置在Modules/Python 源目录中的目录中。

python python-c-api python-3.x

5
推荐指数
1
解决办法
673
查看次数

如何在不构建其 C 扩展的情况下 pip 安装包?

是否有可能pip install package提供可选的 C 扩展,但专门禁用编译这些扩展的过程?

此类包的示例如下:

python pip setuptools python-c-api

5
推荐指数
1
解决办法
1374
查看次数

修改或重新引发 C API 中的 Python 错误

我有一些代码尝试将对象解析为整数:

long val = PyLong_AsLong(obj);
if(val == -1 && PyErr_Occurred()) {
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

obj是一个普通的PyObject *,并PyLong_AsLong引发一个非常通用的TypeErrorifobj不是整数。

我想将错误消息转换为更具信息性的内容,因此我想修改现有的错误对象,或者重新引发它。

我当前的解决方案是这样做:

long val = PyLong_AsLong(obj);
if(val == -1 && PyErr_Occurred()) {
    PyErr_Clear();
    PyErr_Format(PyExc_TypeError, "Parameter must be an integer type, but got %s", Py_TYPE(obj)->tp_name);
    return -1;
}
Run Code Online (Sandbox Code Playgroud)

这是重新引发错误的正确方法吗?具体来说,

  1. 我需要打电话吗PyErr_Clear?我怀疑它正确地减少了现有的异常对象,但我不确定。
  2. 我可以修改当时已经抛出的错误消息而不重新引发它吗?
  3. 有没有一个选项可以做相当于raise new_err from old_err

我不确定如何PyErr_SetExcInfo在这种情况下使用,尽管我的直觉告诉我它可能在某种程度上相关。

python exception python-c-api python-3.x

5
推荐指数
1
解决办法
1115
查看次数

Python C 扩展向异常添加属性

我正在包装一个 C 库,该库在失败时返回有限数量的错误代码之一。当错误发生时,我想将错误代码添加为 C 异常的属性,以便 Python 代码可以检索它并将错误代码映射到人类可读的异常。这可能吗?

例如我想在Python层执行此操作:

try:
    call_my_library_func()
except MyLibraryError as ex:
    print("Error code was %s" % ex.code)
Run Code Online (Sandbox Code Playgroud)

我能达到的最接近但我不喜欢的方法是使用PyErr_SetObject

PyObject *tuple = PyTuple_New(2);
PyTuple_SetItem(tuple, 0, PyUnicode_FromString("Helpful error message"));
PyTuple_SetItem(tuple, 1, PyLong_FromLong(257));
//PyErr_SetString(MyLibraryError, "Helpful error message\n");
PyErr_SetObject(MyLibraryError, tuple);
Run Code Online (Sandbox Code Playgroud)

然后我可以这样做:

try:
    call_my_library_func()
except MyLibraryError as ex:
    message, code = ex.args[0], -1
    if len(ex.args > 1):
        code = ex.args[1]
Run Code Online (Sandbox Code Playgroud)

python python-c-api python-3.x

5
推荐指数
1
解决办法
1193
查看次数

如何使用正确的 dll 文件在 Cython C 扩展中启用第 3 方 C 库?

我有一个 C 函数,涉及使用 zstd 解压缩数据。我正在尝试使用 Cython 调用该函数。

使用文档中的此页面作为指南,我可以毫无问题地编译和运行下面的代码。

(我实际上并没有在这里使用 zstd lib)

// hello.c
#include <stdio.h>
#include <zstd.h>

int hello() {
   printf("Hello, World!\n");
   void *next_in = malloc(0);
   void *next_out = malloc(0);
   return 0;
}

# Hello.pyx

cdef extern from "hello.c":
  int hello()

cpdef int callHello():
  hello()

# hello_wrapper.setup.py

from setuptools import setup, Extension
from Cython.Build import cythonize

ext_modules = [
    Extension(
        "hello_wrapper",
        ["hello_wrapper.pyx"],
        libraries=["zstd"],
        library_dirs=["path/to/zstd/lib"],
        include_dirs=['path/to/zstd/include'],
    )
]

setup(
    ext_modules = cythonize(ext_modules, gdb_debug=True)
)
Run Code Online (Sandbox Code Playgroud)

使用如下命令我得到预期的输出:

>py hello_wrapper.setup.py build_ext --inplace
>py …
Run Code Online (Sandbox Code Playgroud)

c python dll cython python-c-api

5
推荐指数
1
解决办法
1864
查看次数

如何确定 PyObject 是否是 numpy PyArrayObject

我是 Python C-API 的新手。

目前我通过以下方式从嵌入式 Python 模块获取对象

PyObject* a = (PyObject*) PyObject_GetAttrString(pModule, "a");
std::cout << "a as long is " << PyLong_AsLong(a) << std::endl;
Run Code Online (Sandbox Code Playgroud)

我通过访问 numpy 对象

PyArrayObject* array = (PyArrayObject*) PyObject_GetAttrString(pModule, "A");
Run Code Online (Sandbox Code Playgroud)

如何测试该对象是否真的是 a PyArrayObject?换句话说,如何通过 Python 来做我想做的事情isinstance(a, numpy.ndarray)

python numpy python-c-api

5
推荐指数
1
解决办法
1597
查看次数

使用Python C API命名参数?

如何使用Python C API模拟以下Python函数?

def foo(bar, baz="something or other"):
    print bar, baz
Run Code Online (Sandbox Code Playgroud)

(即,可以通过以下方式调用它:

>>> foo("hello")
hello something or other
>>> foo("hello", baz="world!")
hello world!
>>> foo("hello", "world!")
hello, world!
Run Code Online (Sandbox Code Playgroud)

)

c python named-parameters python-c-api

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

在嵌入式Python解释器中打印变量

我编写了一个嵌入Python的小程序.我正在使用Py_Initialize()和Py_Finalize()正确设置它,并且能够使用PyRun_SimpleString或PyRun_SimpleFile运行脚本.但是,我不知道在打印变量时如何模仿Python自己的解释器的行为.

特别:

a = (1, 2, 3)
print a
Run Code Online (Sandbox Code Playgroud)

适合我的工作:打印出来(1,2,3)

然而:

a = (1, 2, 3)
a
Run Code Online (Sandbox Code Playgroud)

什么都没有打印出来.在Python自己的解释器中,这也会打印出(1,2,3).如何让我的代码执行用户期望的操作并打印出值?

提前致谢!

c python interpreter python-embedding python-c-api

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

如何将Python布尔对象转换为C int(或C++ boolean)(Python C API)

我有一个变量PyObject,我知道是一个Python bool.它是TrueFalse(例如.Py_TruePy_False).现在我想以某种方式将其转换为C++.

使用字符串执行此操作并不是很难,有一个辅助函数 - PyBytes_AsString将python字符串转换为C字符串.现在我需要像boolean那样的东西(或者因为boolC中没有,所以需要int ).

或者如果没有转换,也许某些功能可以与true或false进行比较?有点像int PyBool_IsTrue(PyObject*)

以下是一些示例代码,可以更轻松地理解我需要的内容:

#include <Python.h>

int main()
{
    /* here I create Python boolean with value of True */
    PyObject *b = Py_RETURN_TRUE;
    /* now that I have it I would like to turn in into C type so that I can determine if it's True or False */
    /* something like */
    if (PyBool_IsTrue(b))
    { /* it's true! …
Run Code Online (Sandbox Code Playgroud)

c python python-c-api

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