我正在用 Objective-C 编写一个轻量级接口,该接口能够执行 python 脚本并在 Objective-C 和 Python 之间来回传递数据。我已经研究了 PyObjC 和 ObjP,但我都不是我想要的(因为我正在为 iOS <= 6.0.1 开发 PyObjC 不会编译对 NSMapTable 的大量使用)。
所以基本上我在 Objective-C 中创建了一个名为“ObjC_Class”的 Python 类型(创意,不是吗?),我希望这个 Python 对象几乎类似于 ObjC 对象。所以我决定重写类的__getattr __函数,这样我就可以访问该类的 ObjC 等价物的任意方法和属性。
这是代码:
static PyObject * ObjC_Class_getattro(ObjC_Class *self, PyObject *name)
{
NSString *attrName = [NSString stringWithCString:PyString_AsString(name) encoding:NSUTF8StringEncoding];
NSLog(@"Calling Object: %@", self->object);
if([self->object respondsToSelector:NSSelectorFromString(attrName)])
{
methodName = attrName;
//PyObject* (*fpFunc)(PyObject*,PyObject*) = ObjC_Class_msg_send;
PyMethodDef methd = {[attrName UTF8String],ObjC_Class_msg_send,METH_VARARGS,[attrName UTF8String]};
PyObject* pyName = PyString_FromString(methd.ml_name);
PyObject* pyfoo = PyCFunction_NewEx(&methd,(PyObject*)self,pyName);
Py_DECREF(name);
return pyfoo;
}
else
{
return name;
}
}
现在,当我说:
示例 #1
from ObjC import ObjC_Class
new = ObjC_Class('UIView')
new.backgroundColor("asdf", 42, "some_random_string") # This does not crash
但是当我运行时:
示例 #2
from ObjC import ObjC_Class
new = ObjC_Class('UIView')
moreStuff = "some_random_string" # or "42" or [1,2,3] or anything else...
new.backgroundColor("asdf", 42, moreStuff) # !!! This does crash
它崩溃说:
error: address doesn't contain a section that points to a section in a object file
当我尝试调用不存在的函数时,我看到了这个错误,但我无法想象为什么第一个会起作用,而第二个不会。
下面是 ObjC_Class_msg_send 函数的实现:
static PyObject* ObjC_Class_msg_send(PyObject *self, PyObject *args)
{
NSLog(@"Entering...");
NSMutableArray *tmp = [[NSMutableArray alloc] init];
for(int i=0;i<PyTuple_Size(args);i++)
{
[tmp addObject:Py_to_ObjC(PyTuple_GetItem(args, i))];
}
NSLog(@"Object: %@, Method Name: %@, args: %@", ((ObjC_Class*)self)->object, methodName, tmp);
methodName = @"";
return PyString_FromString("Did it actually work!?!?!");
}
当我运行将 python 变量传递给函数的示例时,它在 ObjC_Class_msg_send 甚至被调用之前崩溃(但在 ObjC_Class_getattro 返回其值之后)。
(哦,请原谅草率的代码......在为这个项目分配太多时间之前,我正在努力运行一个简单的概念验证)
我没有提到的事情:我的 ObjC_Class 有一个名为“object”的元素,它的类型为“id”,它存储了对 Python 对象所代表的 Objective-C 对象的引用......
再补充一点:我正在链接 Python 2.6(.3?),它主要是静态链接的
更新
我已经设法通过将 fpFunc 定义为静态删除 fpFunc 来让它停止崩溃......我什至不知道为什么我把它放在那里(愚蠢的复制+粘贴......):
static PyObject * ObjC_Class_getattro(ObjC_Class *self, PyObject *name)
{
NSString *attrName = [NSString stringWithCString:PyString_AsString(name) encoding:NSUTF8StringEncoding];
NSLog(@"Calling Object: %@", self->object);
if([self->object respondsToSelector:NSSelectorFromString(attrName)])
{
methodName = attrName;
//static PyObject* (*fpFunc)(PyObject*,PyObject*) = ObjC_Class_msg_send; // static now
PyMethodDef methd = {[attrName UTF8String],ObjC_Class_msg_send,METH_VARARGS,[attrName UTF8String]};
PyObject* pyName = PyString_FromString(methd.ml_name);
PyObject* pyfoo = PyCFunction_NewEx(&methd,(PyObject*)self,pyName);
Py_DECREF(name);
return pyfoo;
}
else
{
return name;
}
}
但是......现在Python抛出错误(当我将python变量作为参数传递时,即:上面的示例#2):
SystemError: Objects/methodobject.c:120: bad argument to internal function
:(我以前从未见过这个...