我正在写一个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指针的最佳方法是什么?我正在挖掘文档,但我没有找到类似的东西.
谢谢.
将包含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值的元组。
在 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) 给定两个PyObject*s,我如何在 C API 中比较它们?
我一开始想到a == b,但它显然是不正确的,因为它会比较指针而不是对象。我正在寻找a == b(不是a is b)Python C API 中的 Python 等价物。
我正在尝试编译一个 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) 我试图通过从 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) 我在这里查看一些示例代码(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 …
如果我在 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) 我正在尝试使用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) 我正在尝试运行以下代码:
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指示异常发生。如何获得此例外?