当我有返回一些联合的方法时,我遇到了与 objc_msgSend 运行时调用相关的问题。
我正在通过 libffi 调用 objc_msgSend 函数,如果我有小于 16B 的联合,一切都很好,但如果联合的大小大于 16B,我会遇到 seg 错误。我尝试使用 objc_msgSend_stret 函数,它通过了,但是我得到了返回联合的错误值,我不确定哪个函数调用了联合。
有谁知道目标 c 中的联合,它们在 objc 运行时中是如何处理的?
当我有返回一些联合的方法时,我遇到了与 objc_msgSend 运行时调用相关的问题。
我正在通过 libffi 调用 objc_msgSend 函数,如果我有小于 16B 的联合,一切都很好,但如果联合的大小大于 16B,我会遇到 seg 错误。我尝试使用 objc_msgSend_stret 函数,它通过了,但是我得到了返回联合的错误值,我不确定哪个函数调用了联合。
有谁知道目标 c 中的联合,它们在 objc 运行时中是如何处理的?
当您使用 ; 时,这是一个 HUUUUGE 问题objc_msgSend
;基本上,大多数 ABI 都喜欢将它们的返回值放在寄存器中(这里是勇敢和好奇的所有血腥细节:http: //developer.apple.com/library/mac/#documentation/DeveloperTools/Conceptual/LowLevelABI/000 -Introduction/introduction.html),但有些对象无法放入寄存器中(这就是为什么 union size <= 16 适合您的原因)。您需要objc_msgSend_stret
使用您希望工会被塞入的地址打电话。
另一个很好的参考:http ://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html
解决方案:不要强制转换和调用objc_msgSend
,而是强制转换和调用objc_msgSend_stret
。
void objc_msgSend_stret(void * stretAddr, id theReceiver, SEL theSelector, ...)
所以你的演员将是(比如使用 objc_msgSend 调用具有命名参数的Objective C函数):
union myUnion {
int a, b;
char c;
double d;
};
// For objc_msgSend_stret
void (*objc_msgSend_stretTyped)(union myUnion* stretAddr, id self, SEL _cmd, float bar) = (void*)objc_msgSend_stret;
union myUnion u;
float pi = 4;
objc_msgSend_stretTyped(&u, obj, sel_getUID(sel), pi);
这是我设法让 objc_msgSend_stret 工作的方法:
#import "ViewController.h"
#import <objc/runtime.h>
#import <objc/objc.h>
@interface ViewController ()
@end
union myUnion {
int myArray[32];
int a,b,c,d;
};
void doStuff(id obj, SEL sel);
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
doStuff(self, @selector(doStuff:));
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (union myUnion) doStuff: (int)myInt {
NSLog(@"Pi equals %d", myInt);
union myUnion u;
for(int i=0; i<32; i++) {
u.myArray[i] = i*i*i*i-1;
}
return u;
}
@end
void doStuff(id obj, SEL sel) {
int pi = 4;
NSLog(@"myUnion is: %luB", sizeof(union myUnion));
NSLog(@"Sizeof(int) = %luB ... Sizeof(char) = %lub ... sizeof(double) = %luB", sizeof(int), sizeof(char), sizeof(double));
union myUnion u = ((union myUnion(*)(id, SEL, int))objc_msgSend_stret)(obj, sel, pi);
NSLog(@"Union u = {%d, %d, %d, %d}", u.myArray[30], u.myArray[29], u.myArray[28], u.myArray[27]);
}