1

私は Python から目的の c にアクセスするための lib を作成しているので、目的の c へのアクセスには Cython と目的の c ランタイムを使用しています。ユーザーがこの方法でプロパティを宣言するとしましょう:

@property (assign) NSString *prop_nsstring_dyn;

そして、このプロパティで @dynamic を使用したいと考えています。よし、このマクロを使ってみましょう:

#define ADD_DYNAMIC_PROPERTY(PROPERTY_TYPE, PROPERTY_NAME, SETTER_NAME) \
\
@dynamic prop_nsstring_dyn; \
- ( PROPERTY_TYPE ) PROPERTY_NAME \
{ \
printf("returning\n"); \
return ( PROPERTY_TYPE ) objc_getAssociatedObject(self, @selector(PROPERTY_NAME)); \
} \
\
- (void) SETTER_NAME :( PROPERTY_TYPE ) PROPERTY_NAME \
{ \
printf("setting\n"); \
objc_setAssociatedObject(self, @selector(PROPERTY_NAME), PROPERTY_NAME, OBJC_ASSOCIATION_RETAIN); \
} \

この後、@implementation でこれを呼び出すことができます。

ADD_DYNAMIC_PROPERTY(NSString*, prop_nsstring_dyn, setProp_nsstring_dyn);

そして、この方法で目的 c から呼び出すと:

c.prop_nsstring_dyn = @"test str";

また

c.prop_nsstring_dyn;

ゲッターとセッターが正しく呼び出されます。しかし、目的の C ランタイムからこの動的プロパティの値を設定および取得する必要があるため、objc_getIvar/objc_setIvar ゲッターおよびセッターなどの関数を使用すると、まったく呼び出されず、結果として null ポインターが取得されます。

get/set 関数を呼び出す方法について何か知っている人はいますか。目的のCランタイムからの動的プロパティの?

ありがとうございました!

4

2 に答える 2

4

ゲッターとセッターが正しく呼び出されます。しかし、目的の C ランタイムからこの動的プロパティの値を設定および取得する必要があるため、objc_getIvar/objc_setIvar ゲッターおよびセッターなどの関数を使用すると、まったく呼び出されず、結果として null ポインターが取得されます。

これはあなたの間違いです。別のオブジェクトのプロパティを呼び出しobjc_getIvarたり、操作したりしないでください。objc_setIvarプロパティは ivar ではありません。プロパティは、メソッドを実装する約束です。これらのメソッドがどのように実装されているかを推測することはできません。あなたは確かにそれらがへの呼び出しと同等であると仮定することはできませんobjc_getIvar(あなたが発見しているように)。

KVCを使用した@NathanDayのアプローチはまともなアプローチですが[obj valueForKey:@"foo"][obj foo]. それでも、それは近いです。

まず、明確にするために、実際には「オブジェクトのプロパティの値を取得する」わけではありません。実際には「オブジェクト メソッドを呼び出す」ことさえしません。オブジェクトにメッセージを送信すると、オブジェクトは結果を返します。プロパティは、特定のメッセージ (セレクター) に応答することを宣言するための便利な方法です。

メッセージを正しく送信するには、 に電話する必要がありますobjc_msgSend。戻り値が浮動小数点であるか構造体であるかに応じて、いくつかの形式があることに注意してください (これは、 を使用する利点ですvalueForKey:。これにより、すべての戻り値が同じように見えるため、どの形式かを知る必要はありません。objc_msgSend呼び出す)。idいずれにせよ、戻り値が であるかスカラーである可能性があるため、戻り値を解釈する方法を知る必要があります。

最も一般的なケース (たとえば、クラスが を実装している場合forwardingTargetForSelector:) では、実行時にセレクターの戻り値の型を決定することはできないと思います。この情報は、コンパイル時にヘッダー ファイルから取得する必要があります。しかし、ほとんどの場合、実行時class_getPropertyに and property_getAttributes、 orclass_getInstanceMethodおよびを使用して戻り値を決定できmethod_getReturnTypeます (両方をチェックする必要があります。開発者が で「プロパティのようなもの」を宣言しなければならないという規則はありません@property)。

メソッドの実装への実際の C 関数ポインターを取得することは可能ですが、通常はオブジェクトの外部からこれを行うべきではありません。「その名前のメソッドを呼び出す」に変換されないメッセージを ObjC オブジェクトが処理する方法は多数あります。メッセージを渡し、オブジェクト自体が処理できるようにする必要があります。

しかし、プロパティの読み取りと書き込みについては、おそらく Nathan の KVC アプローチで十分です。それでも、PyObjC はすでにこれらの問題を解決しているので、PyObjC をもう一度確認することを強くお勧めします。少なくとも、私は彼らのコードを綿密に研究したいと思います。

于 2013-07-29T15:01:50.083 に答える
2

NSObject メソッドを使用して、setter メソッドと getter メソッドを間接的に呼び出すことができます。

- [NSObject setValue:(id) forKey:(NSString *)];
- (id)[NSObject valueForKey:(NSString *)];

ここで、プロパティが unsigned long、double などのプリミティブ型の場合、キーはプロパティ名です。次に、setValue および value メソッドが NSNumber に相当するものを処理します。

また、他のメソッドを呼び出すのと同じ方法でプロパティ セッターとゲッターを呼び出すことができるため、通常のメソッドで使用できるすべての動的メソッド呼び出し機能を使用できます。

于 2013-07-29T13:41:36.827 に答える