我正在尝试使用服务器连接器对象来实现JSON-RPC解决方案,该服务器连接器对象以某种方式从服务器获取可用功能列表
NSDictionary *functions = [server
callJSONFunction: @"exposedFunctions" arguments: nil];
这是一个简化的描述,因为callJSONFunction
实际上触发了异步NSURLConnection。
函数列表的一个元素包括一个描述目标c选择器的字符串,将使用上述机制调用的原始函数名,函数签名和一个可选的参数名称数组。
因此,例如,函数列表可能如下所示:
(
@"someFunctionWithArgumentOne:argumentTwo:" =
{
signature = @"@@:@@",
functionName = @"someFunction",
arguments = ( @"arg_one", @"arg_two" )
},
@"anotherFunction" =
{
signature = @"@@:",
functionName = @"anotherFunction"
}
)
成功检索功能列表后,选择器将在循环中使用class_addMethod
添加到服务器连接器实例中:
for ( NSString *selectorName in functions ) {
SEL aSelector = NSSelectorFromString ( selName );
IMP methodIMP = class_getMethodImplementation (
[ self class ], @selector ( callerMethod: ) );
class_addMethod ( [ self class ], aSelector, methodIMP, "v@:@@@@" );
}
其中callerMethod:
是用于组成实际请求的包装函数,包括作为NSString的函数名和形式为
{ @"argument1_name" = arg1, @"argument2_name" = arg2, ... }
因此签名为“v @:@@”。然后callerMethod在服务器上调用callJSONFunction
。
经过这段精疲力尽的介绍(我的不好,我只是不知道,如何缩短它)我终于明白了:要涵盖不同数量论点的可能性,
我将calllerMethod定义为
- (void) callerMethod: (id)argument, ... { }
其中我使用stdarg.h
中的va_ *宏来获取传递的参数。但是当我通过调用
[serverConnector someFunctionWithArgumentOne: @"Argument 1"
argumentTwo: @"Argument 2" ];
id arg = va_arg ( list, id);
返回的第一个参数始终为@"Argument 2"
!
我真的很感激为什么会发生这种情况的所有理论和解释。这件事真让我疯了!
答案 0 :(得分:15)
Var-args不会映射到常规参数传递非常整齐。参数的编码实际上是特定于体系结构的,并且充满了非常有趣的细节,有时看起来它们是自相矛盾的(直到你发现关于规则的一个例外的注释,使整个事物连贯一致)。如果你真的想要一个好的阅读[讽刺意图],那么去看看ppc64如何处理长双打;有些情况下,double的一半将在寄存器中,另一半在堆栈中。 Whee!
上面很长,由于疤痕而略带泡沫,段落就是说你不能透明地将一个函数的调用转发到另一个函数,其中两个函数采用不同的参数。由于Objective-C方法实际上只是一个函数,因此方法也是如此。
相反,请使用NSInvocation,因为它旨在隐藏包含任何给定平台ABI的参数编码的所有深奥细节。
但是,在您的情况下,您可以通过定义一组定义所有可能的论证组合的函数来逃避class_addMethod()。您甚至不需要创建字典,因为您可以使用dlsym()
函数来查找正确的函数。即。
id trampolineForIdIdSELIdIdInt(id self, SEL _cmd, id obj1, id obj2, int) {
... your magic here ...
}
然后,您可以将类型字符串“@@:@@ i”翻译成该函数名称并将其传递给dlsym
,获取结果并使用class_addMethod()
....
我确实有义务提及this book,因为它是一种“哇......人......如果我们将类表示为称为元类的对象,那么它们本身就可以表示为类,比如,将宇宙重新定义为元类和类“这一思路的终极目标。”
答案 1 :(得分:1)
另见Gregor Kiczales和Andreas Paepcke的unfinished book。