我正在尝试使用C扩展文件构建共享库,但首先我必须使用以下命令生成输出文件:
gcc -Wall utilsmodule.c -o Utilc
Run Code Online (Sandbox Code Playgroud)
执行命令后,我收到此错误消息:
utilsmodule.c:1:20:致命错误:Python.h:没有这样的文件或目录编译终止.
事实上我已经通过互联网尝试了所有建议的解决方案,但问题仍然存在...我也没有问题Python.h.我设法在我的机器上找到该文件......任何人在遇到同样的问题之前?
我要问的问题似乎是Python使用__new__和__init__的重复?但是无论如何,我还不清楚到底是什么__new__和__init__它之间的实际区别.
在你急于告诉我__new__是用于创建对象并且__init__用于初始化对象之前,让我说清楚:我明白了. 事实上,这种区别对我来说是很自然的,因为我在C++中有经验,我们有新的贴图,它同样将对象分配与初始化分开.
在Python的C API教程解释它是这样的:
新成员负责创建(而不是初始化)该类型的对象.它在Python中作为
__new__()方法公开.... 实现新方法的一个原因是确保实例变量的初始值.
所以,是的 - 我得到了什么__new__,但尽管如此,我仍然不明白为什么它在Python中有用.给出的示例说,__new__如果要"确保实例变量的初始值" ,这可能很有用.那么,这究竟是什么意思__init__呢?
在C API教程中,显示了一个示例,其中创建了一个新类型(称为"Noddy"),并__new__定义了Type的函数.Noddy类型包含一个名为的字符串成员first,并且此字符串成员初始化为空字符串,如下所示:
static PyObject * Noddy_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
.....
self->first = PyString_FromString("");
if (self->first == NULL)
{
Py_DECREF(self);
return NULL;
}
.....
}
Run Code Online (Sandbox Code Playgroud)
请注意,如果没有__new__此处定义的方法,我们必须使用PyType_GenericNew,它只是将所有实例变量成员初始化为NULL.因此,该__new__方法的唯一好处是实例变量将以空字符串开头,而不是NULL. 但是为什么这个有用,因为如果我们关心确保我们的实例变量被初始化为某个默认值,我们可以在 …
假设我们有关于为Python编写C扩展模块Noddy的教程中定义的类型.现在我们要创建一个派生类型,只覆盖它的__new__()方法Noddy.
目前我使用以下方法(为了便于阅读而删除了错误检查):
PyTypeObject *BrownNoddyType =
(PyTypeObject *)PyType_Type.tp_alloc(&PyType_Type, 0);
BrownNoddyType->tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
BrownNoddyType->tp_name = "noddy.BrownNoddy";
BrownNoddyType->tp_doc = "BrownNoddy objects";
BrownNoddyType->tp_base = &NoddyType;
BrownNoddyType->tp_new = BrownNoddy_new;
PyType_Ready(BrownNoddyType);
Run Code Online (Sandbox Code Playgroud)
这有效,但我不确定它是不是正确的方法.我本来期望我也必须设置Py_TPFLAGS_HEAPTYPE标志,因为我在堆上动态分配类型对象,但这样做会导致解释器中出现段错误.
我还想过明确地type()使用PyObject_Call()或类似地调用,但我放弃了这个想法.我需要将函数包装BrownNoddy_new()在Python函数对象中并创建一个映射__new__到此函数对象的字典,这看起来很愚蠢.
最好的方法是什么?我的方法是否正确?我错过了接口功能吗?
python-dev邮件列表(1) (2)上的相关主题有两个主题.从这些线程和一些实验中我推断出Py_TPFLAGS_HEAPTYPE除非通过调用分配类型,否则我不应该设置type().这些线程中有不同的建议是手动分配类型还是调用更好type().如果我知道推荐的方法来包装应该插入tp_new插槽的C函数,我会对后者感到满意.对于常规方法,这一步很简单 - 我可以PyDescr_NewMethod()用来获得一个合适的包装器对象.我不知道如何为我的__new__()方法创建这样的包装器对象- 也许我需要未记录的函数PyCFunction_New()来创建这样的包装器对象.
我想调用一个在C语言的python模块中定义的自定义函数.我有一些初步代码可以做到这一点,但它只是将输出打印到stdout.
mytest.py
import math
def myabs(x):
return math.fabs(x)
Run Code Online (Sandbox Code Playgroud)
TEST.CPP
#include <Python.h>
int main() {
Py_Initialize();
PyRun_SimpleString("import sys; sys.path.append('.')");
PyRun_SimpleString("import mytest;");
PyRun_SimpleString("print mytest.myabs(2.0)");
Py_Finalize();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如何将返回值提取到C double并在C中使用它?
如何使用Python C API复制以下Python代码?
class Sequence():
def __init__(self, max):
self.max = max
def data(self):
i = 0
while i < self.max:
yield i
i += 1
Run Code Online (Sandbox Code Playgroud)
到目前为止,我有这个:
#include <Python/Python.h>
#include <Python/structmember.h>
/* Define a new object class, Sequence. */
typedef struct {
PyObject_HEAD
size_t max;
} SequenceObject;
/* Instance variables */
static PyMemberDef Sequence_members[] = {
{"max", T_UINT, offsetof(SequenceObject, max), 0, NULL},
{NULL} /* Sentinel */
};
static int Sequence_Init(SequenceObject *self, PyObject *args, PyObject *kwds)
{
if (!PyArg_ParseTuple(args, "k", &(self->max))) { …Run Code Online (Sandbox Code Playgroud) 假设我的对象布局定义为:
typedef struct {
PyObject_HEAD
// Other stuff...
} pyfoo;
Run Code Online (Sandbox Code Playgroud)
...和我的类型定义:
static PyTypeObject pyfoo_T = {
PyObject_HEAD_INIT(NULL)
// ...
pyfoo_new,
};
Run Code Online (Sandbox Code Playgroud)
如何pyfoo在C扩展中的某个位置创建新实例?
说明以下内容是正确的:
如果在C函数中创建了Python对象,但该函数没有返回它,INCREF则不需要,但是a DECREF.
[false]如果函数确实返回了它,你需要INCREF在接收返回值的函数中.[/ false]
当分配了C类型的变量作为属性,如double,int等等,给Python对象,没有INCREF或DECREF需要.
将Python对象作为属性分配给其他Python对象,如下所示:
PyObject *foo;
foo = bar // A Python object
tmp = self->foo;
Py_INCREF(foo);
self->foo = foo;
Py_XDECREF(tmp);
//taken from the manual, but it is unclear if this works in every situation
Run Code Online (Sandbox Code Playgroud)编辑: - >我可以在任何情况下安全地使用它吗?(没有碰到一个导致我问题的地方)
DECREF用于其作为属性的每个其他Python对象,但不适用于C类型的属性.编辑
'C type as a attribute'是指bar和baz:
typedef struct {
PyObject_HEAD
PyObject *foo;
int bar;
double baz;
} FooBarBaz;
Run Code Online (Sandbox Code Playgroud) 我有一个程序,在它运行期间有时需要调用python来执行某些任务.我需要一个调用python并捕获pythons stdout并将其放入某个文件的函数.这是函数的声明
pythonCallBackFunc(const char* pythonInput)
Run Code Online (Sandbox Code Playgroud)
我的问题是捕获给定命令(pythonInput)的所有python输出.我没有python API的经验,我不知道什么是正确的技术来做到这一点.我尝试过的第一件事是使用Py_run_SimpleString重定向python的sdtout和stderr,这是我编写的代码的一些例子.
#include "boost\python.hpp"
#include <iostream>
void pythonCallBackFunc(const char* inputStr){
PyRun_SimpleString(inputStr);
}
int main () {
...
//S0me outside functions does this
Py_Initialize();
PyRun_SimpleString("import sys");
PyRun_SimpleString("old_stdout = sys.stdout");
PyRun_SimpleString("fsock = open('python_out.log','a')");
PyRun_SimpleString("sys.stdout = fsock");
...
//my func
pythonCallBackFunc("print 'HAHAHAHAHA'");
pythonCallBackFunc("result = 5");
pythonCallBackFunc("print result");
pythonCallBackFunc("result = 'Hello '+'World!'");
pythonCallBackFunc("print result");
pythonCallBackFunc("'KUKU '+'KAKA'");
pythonCallBackFunc("5**3");
pythonCallBackFunc("prinhghult");
pythonCallBackFunc("execfile('stdout_close.py')");
...
//Again anothers function code
PyRun_SimpleString("sys.stdout = old_stdout");
PyRun_SimpleString("fsock.close()");
Py_Finalize();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?此外,由于某种原因PyRun_SimpleString在得到一些数学表达式时什么都不做,例如PyRun_SimpleString("5**3")什么都不打印(python …
我正在将Python解释器嵌入到C程序中.但是,可能会发生这样的情况:运行某些python脚本时PyRun_SimpleString()会遇到无限循环或执行太长时间.考虑PyRun_SimpleString("while 1: pass");在阻止主程序阻止我认为我可以在一个线程中运行解释器.
如何停止在线程中运行的嵌入式解释器中执行python脚本而不会终止整个过程?
是否可以将异常传递给解释器?我应该将脚本包装在其他可以收听信号的脚本下吗?
PS:我可以在一个单独的过程中运行python,但这不是我想要的 - 除非它是最后的手段......
更新:
所以,它现在有效.再次感谢Denis Otkidach!
如果我看到这一点,你必须做两件事:告诉解释器停止并return -1在与PyRun_SimpleString()运行的同一个线程中.
要停止,有一些可能性:PyErr_SetString(PyExc_KeyboardInterrupt, "...")或者PyErr_SetInterrupt()- 第一个可能让Python运行更多指令然后停止,后者立即停止执行.
要return -1使用Py_AddPendingCall()注入一个函数调用成Python执行.自2.7和3.1版以来,文档提到它,但它也运行在早期的Pythons上(这里是2.6).从2.7和3.1它也应该是线程安全的,这意味着你可以在不获取GIL(?)的情况下调用它.
所以可以重写下面的例子:
int quit() {
PyErr_SetInterrupt();
return -1;
}
Run Code Online (Sandbox Code Playgroud) python multithreading process embedded-language python-c-api
这是python文档(http://docs.python.org/extending/extending.html)中的一个简单示例:
static PyObject *
spam_system(PyObject *self, PyObject *args)
{
const char *command;
int sts;
if (!PyArg_ParseTuple(args, "s", &command))
return NULL;
sts = system(command);
return Py_BuildValue("i", sts);
}
Run Code Online (Sandbox Code Playgroud)
如果我想将另一个布尔参数传递给函数 - 这是什么"正确"的方法呢?
似乎没有传递给PyArg_ParseTuple()的bool选项.所以我想到了以下几点:
这些中哪一个更好?其他选择?
python ×10
python-c-api ×10
c ×4
c++ ×2
gcc ×1
generator ×1
iterator ×1
process ×1
python-2.x ×1
redirect ×1