【问题标题】:How to pass variable number of args to a variadic function如何将可变数量的参数传递给可变参数函数
【发布时间】:2011-01-16 04:51:46
【问题描述】:

我有一个带有签名的可变参数函数:

- (id)initWithNumVertices:(NSUInteger)inCount, ...;

但我无法弄清楚如何从 可变 数量的顶点构造省略号部分。如何做到这一点?

编辑:抱歉,我没有要求编写此函数的方法,我要求的是使用 未知 个变量来调用它的方法。该函数采用结构而不是对象。

如果参数的数量已知,我可以这样做:

[[MyObject alloc] initWithNumVertices:4, v[0], v[1], v[2], v[3]];

但是当顶点数未知时,我该如何调用呢?

【问题讨论】:

  • 澄清一下,这些顶点是如何表示的?它们是对象、原始类型等吗?这与我的回答有关。
  • 顶点是一个由 2 个浮点数组成的结构体。

标签: objective-c c variadic-functions


【解决方案1】:

如果在编译时不知道参数的数量,我认为不可能调用可变参数函数。如果您想避免使用 NSArray 的开销,将多个 C 结构体传递给方法的标准方法是使用标准 C 数组。

- (id)initWithVertices:(Vertex *)vertices count:(NSUInteger)count;

NSIndexPath's -indexPathWithIndexes:length: 是一个也使用这种模式的例子,还有很多其他的,这在 Cocoa 中相当常见。

【讨论】:

    【解决方案2】:

    编辑:只需使用原生 C 数组即可。可变参数方法在这里对您没有帮助。


    在您的情况下,由于您有未指定数量的参数,您必须以这种形式重写它:

    - (id)initWithVertices:(vertex)firstVertex;
    

    它运行一个while循环,直到它到达一个指定为非法的顶点(这将是你的断点),有点像这样:

    vertex currentVertex, invalidVertex = // some invalid value, like {-1, -1}
    while ((currentVertex = va_arg(args, vertex) != invalidVertex) {
        // initialization code with the current vertex
        // when we hit 'invalidVertex', which will be at the end of the list, stop
    }  
    

    这样的代码必须像这样运行:

    [[MyObject alloc] initWithVertices:firstVertex, secondVertex, thirdVertex, nullVertex];
    

    nullVertex 必须在列表末尾才能指定最后一个有效顶点(很像NSArrayarrayWithObjects: 方法必须在列表末尾有nil) .

    【讨论】:

    • 谢谢,但我已经有这个功能了。我只是不知道如何为 X(未知)顶点数的一般情况调用它。这就像传递一个数组,只是由于性能原因我不想传递一个 NSArray。
    • 我更新的答案对您仍然无效吗?您为什么担心性能原因?你能再详细说明一下吗?
    • 如何调用 initWithVertices: 对于 X 顶点的一般情况?
    • 你没有。如果它真的没有指定,请传入一个数组。你为什么要避开他们?
    • 顶点和CGPoint一样,但是我不想每次创建对象时都将它们编码和解码为NSValues,因为我每秒创建和销毁这些数千次。如果像 NSArray 这样的集合对象是不可避免的,我会使用它,但我想看看是否有更快的替代方案。可变参数 args 似乎是答案,只是我不知道如何称呼它。
    【解决方案3】:

    你是问如何分离论点?

    [[YourObject alloc] initWithNumVertices:7, 8, 9, 10];
    

    编辑 |哦,我想我明白你在问什么。您想动态调用此方法,例如使用objc_msgSend() 或通过NSInvocation?如果是这样,请忽略我的回答。

    【讨论】:

    • 是的,只是我不能这样做,因为我不知道有多少顶点。
    • 对不起,我误解了你的问题。
    【解决方案4】:

    如果您还没有,请查看 libffi (`man ffi'):

    描述 外部函数接口提供了一种机制,通过该机制 函数可以生成调用 运行时的另一个函数 需要知识 编译时调用函数的接口。

    如果我理解正确,您应该可以使用此调用 objc_msgSend()

    【讨论】:

      猜你喜欢
      • 2014-10-20
      • 1970-01-01
      • 2023-01-21
      • 2010-11-28
      • 2015-09-23
      • 1970-01-01
      • 1970-01-01
      • 2014-03-06
      • 1970-01-01
      相关资源
      最近更新 更多