gpt4 book ai didi

objective-c - iOS NSInvocation setArgument : atIndex: does not work with struct on ARM builds

转载 作者:行者123 更新时间:2023-11-29 11:14:44 24 4
gpt4 key购买 nike

我在使用包含 double 或任何未对齐的 64 位类型的结构设置 NSInvocation 的参数时遇到一个奇怪的问题(我在结构的开头用 char 偏移它)。问题是一些字节在设置参数后被清除。这个问题在ARM7上出现,但在iOS模拟器上没有。

我正在使用 LLVM 3.0 和 Xcode 4.2

这是我的代码和测试结果:

NSInvocation+Extension.h

@interface NSInvocation (Extension)

+ (NSInvocation*) invocationWithTarget: (id)aTarget
selector: (SEL)aSelector
retainArguments: (BOOL)aRetainArguments, ...;

- (void) setArguments: (va_list)aArgList;
- (void) setArguments: (va_list)aArgList atIndex: (NSInteger)aIndex;

@end // NSInvocation (Extension)

NSInvocation+Extension.m

#import <objc/runtime.h>

#import "NSInvocation+Extension.h"


@implementation NSInvocation (Extension)

+ (NSInvocation*) invocationWithTarget: (id)aTarget
selector: (SEL)aSelector
retainArguments: (BOOL)aRetainArguments, ...
{
NSMethodSignature* signature = [aTarget methodSignatureForSelector: aSelector];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature: signature];

if (aRetainArguments)
{
[invocation retainArguments];
}
[invocation setTarget: aTarget];
[invocation setSelector: aSelector];

va_list argList;
va_start(argList, aRetainArguments);
[invocation setArguments: argList];
va_end(argList);

return invocation;
}

- (void) setArguments: (va_list)aArgList
{
[self setArguments: aArgList atIndex: 0];
}

- (void) setArguments: (va_list)aArgList atIndex: (NSInteger)aIndex
{
// Arguments are aligned on machine word boundaries
const NSUInteger KOffset = sizeof(size_t) - 1;

UInt8* argPtr = (UInt8*)aArgList;
NSMethodSignature* signature = [self methodSignature];

// Indices 0 and 1 indicate the hidden arguments self and _cmd respectively.
for (int index = aIndex + 2; index < [signature numberOfArguments]; ++index)
{
const char* type = [signature getArgumentTypeAtIndex: index];
NSUInteger size = 0;
NSGetSizeAndAlignment(type, &size, NULL);
[self setArgument: argPtr atIndex: index];
argPtr += (size + KOffset) & ~KOffset;
}
}

@end // NSInvocation (Extension)

声明要调用的方法和数据结构

- (void) arg1: (char)aArg1 arg2: (char)aArg2 arg3: (TEST)aArg3 arg4: (char)aArg4;

typedef struct test {
char c;
double s;
char t;
void* b;
char tu;
} TEST;

调用代码

TEST df = { 'A', 12345678.0, 'B', (void*)2, 'C' }; 

char buf[100] = {0};

NSInvocation* ik = [NSInvocation invocationWithTarget: self selector: @selector(arg1:arg2:arg3:arg4:) retainArguments: NO, '1', '2', df, '3'];
[ik getArgument: &buf atIndex: 4];

ARM7 上 buf 的内容(字节 8、9、10 和 11 设置为零,这弄乱了 double 值)

41 00 00 00 00 00 00 00 29 8C 67 41 42 00 00 00 02 00 00 00 43 00 00 00

i386 模拟器上 buf 的内容(如预期的那样)

41 00 00 00 00 00 00 C0 29 8C 67 41 42 00 00 00 02 00 00 00 43 00 00 00


最佳答案

首先想到的是,您确实必须使用 va_arg 来访问可变参数列表中的连续参数。您无法像您那样假设参数被安排在一 block 漂亮的连续内存中。一方面,ARM ABI 表示前四个参数在寄存器中传递。

va_list 不一定只是一个指针,它是一个不透明的类型。您对 uint8_t* 的转换几乎肯定是无效的。

关于objective-c - iOS NSInvocation setArgument : atIndex: does not work with struct on ARM builds,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9965116/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com