我在学习python embedded C编程时遇到过问题。
这是我的示例: 读缓冲区.c
#include "Python.h"
static PyObject* Test_IsInstance(PyObject* self, PyObject* args){
PyObject* pTest = NULL;
PyObject* pName = NULL;
PyObject* moduleDict = NULL;
PyObject* className = NULL;
PyObject* pModule = NULL;
pName = PyString_FromString("common");
pModule = PyImport_Import(pName);
if (!pModule){
printf("can not find client.py\n");
Py_RETURN_NONE;
}
moduleDict = PyModule_GetDict(pModule);
if (!moduleDict){
printf("can not get Dict\n");
Py_RETURN_NONE;
}
className = PyDict_GetItemString(moduleDict, "Test");
if (!className){
printf("can not get className\n");
Py_RETURN_NONE;
}
PyObject* subClassName = PyDict_GetItemString(moduleDict, "pyTest");
if (! subClassName){
printf("can not get subClassName\n");
}
int k = PyClass_IsSubclass(subClassName, className);
if (!k){
printf("pyTest is not subclass of Test\n");
}
int r = PyClass_Check(className);
if (!r){
printf("className is not a class\n");
} else {
printf("className is a class\n");
}
PyObject* pInsTest = PyInstance_New(className, NULL, NULL);
PyObject_CallMethod(pInsTest, "py_printT", "()");
int ok = PyArg_ParseTuple(args, "O", &pTest);
if (!ok){
printf("parse tuple error!\n");
Py_RETURN_NONE;
}
if (!pTest){
printf("can not get the instance from python\n");
Py_RETURN_NONE;
}
PyObject_CallMethod(pTest, "py_print", "()");
if (!PyObject_IsInstance(pTest, className)){
printf("Not an instance for Test\n");
Py_RETURN_NONE;
} else {
printf("an instance for Test\n");
}
Py_RETURN_NONE;
}
static PyMethodDef readbuffer[] = {
{"testIns", Test_IsInstance, METH_VARARGS, "test for instance!"},
{NULL, NULL}
};
void initReadBuf(){
PyObject* m;
m = Py_InitModule("ReadBuf", readbuffer);
}
通用.py
class Test(object):
def __init__(self):
print "Test class"
def py_printT(self):
print "Test py_print"
class pyTest(Test):
def __init__(self):
Test.__init__(self)
print "pyTest class"
def py_print(self):
print "pyTest py_print"
客户端.py
from common import pyTest
import ReadBuf as rb
b = pyTest()
rb.testIns(b)
我在python2.7.2上执行时,结果:
Test class
pyTest class
pyTest is not subclass of Test
className is not a class
New instance error
pyTest py_print
an instance for Test
如果我在python2.4.5上执行,结果:
Test class
pyTest class
pyTest is not subclass of Test
className is not a class
New instance error
pyTest py_print
an instance for Test
Exception exceptions.SystemError: 'Objects/classobject.c:528: bad argument to internal function' in 'garbage collection' ignored
Fatal Python error: unexpected exception during garbage collection
Aborted (core dumped)
我的问题:
为什么python2.4.5会抛出异常?
我定义
pyTest
是Test
的子类,为什么结果是pyTest
不是Test<的子类
?为什么当我执行
PyClass_Check
函数时,className
不再是一个类?因为
className
已经不是类了,为什么我执行了PyObject_IsInstance
,结果为真?如果我像下面这样修改Test类的定义,结果是正常的,为什么?
class Test: # don't inherit object any more
最佳答案
问题是 PyClass_*
函数应该仅用于旧式类。
当您从 object
继承时,该类成为新式类,您应该使用 PyType_*
函数,列出 here .
即:
在新型实例上对 PyClass_*
函数的所有调用结果都是伪造的。然而,PyObject_IsInstance
适用于旧式和新式类,这解释了为什么它无论如何都会返回 True
。
显然将 class Test(object)
更改为 class Test
“解决”了奇怪的行为,因为 Test
现在是一个旧式类您应该使用 PyClass_*
函数。
Python2.4 是相当老的 python 版本,可能 API 之间存在一些不一致。您应该为您使用的每个 python 版本重建 C 扩展。 (最新版本的 python 确实有一个稳定的 ABI,但我相信不是 python2.4)。
关于python - 关于 PyClass_Check 和 PyClass_IsSubclass 函数的一些混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21929143/