私は、Pythonスクリプトを実行し、Objective-CとPythonの間でデータをやり取りできるObjective-Cで軽量のインターフェイスを作成しているところです。私は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
存在しない関数を呼び出そうとするとこのエラーが発生しましたが、最初の関数が機能するのに2番目の関数が機能しない理由は想像できません。
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には、Pythonオブジェクトが表すObjective-Cオブジェクトへの参照を格納するタイプ'id'の'object'という名前の要素があります...
もう1つの補足:ほとんど静的にリンクされている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
:(私はこれまでこれを見たことがありません...