【问题标题】:Calling variadic C function from Swift with pointers使用指针从 Swift 调用可变参数 C 函数
【发布时间】:2022-12-11 04:46:33
【问题描述】:

我试图弄清楚如何调用从 Swift 写入指针的可变参数 C 函数,例如 vsscanf,但我不明白如何实际构造指向 Swift 变量的指针列表。

我认为如果我有一个字符串,我可以获得一个 UnsafePointer<CChar> 并在其上调用 vsscanf,但是......我如何告诉它实际写入数据的位置?我如何构建 CVaListPointer 以传递给 vsscanf

var a: Int
var b: Float
"(5, 3.14)".withCString{buffer in
    let r = vsscanf(buffer, "(%d, %f)", /* how do I put a and b here? */)
}

基本上,做与此处相同的事情 (C):

#include <stdio.h>
#include <stdarg.h>

int parse(const char *buffer, char *format, ...)
{
    va_list args;
    va_start(args, format);
    int result = vsscanf(buffer, format, args);
    va_end(args);
    return result;
}

int main(int argc, char const *argv[])
{
    int a;
    float b;
    char s[] = "(5, 3.14)";

    int r = parse(s, "(%d, %f)", &a, &b);

    printf("a: %d, b: %f\n", a, b);
    // "a: 5, b: 3.140000"

    return 0;
}

【问题讨论】:

    标签: swift variadic-functions


    【解决方案1】:

    来自documentation on CVarArgs

    要为 c_api 函数创建包装器,请编写一个采用 CVarArg 参数的函数,然后使用 withVaList(_:_:) 函数调用导入的 C 函数。

    Swift 只导入使用 va_list 作为参数的 C 可变参数函数。不导入使用 ... 可变参数语法的 C 函数,因此不能使用 CVarArg 参数调用。

    您的包装函数可能如下所示:

    func vsscanfSwiftWrapper(
        buffer: UnsafePointer<CChar>,
        format: UnsafePointer<CChar>,
        _ arguments: CVarArg...
    ) -> CInt {
        withVaList(arguments) { vaList in
            vsscanf(buffer, format, vaList)
        }
    }
    

    【讨论】:

    • 对,但我怎么办称呼vsscanfSwiftWrapper?我不明白如何获取指向我的变量的 CVarArgs。
    • 如果您询问如何获取指向ab 的指针而不是值本身,我会查看UnsafeMutablePointer 的文档。
    【解决方案2】:

    像这样:

    var a: Int = 0
    var b: Float = 0
    withUnsafePointer(to: &a) { pointerToA in
        withUnsafePointer(to: &b) { pointerToB in
            withVaList([pointerToA, pointerToB]) { va_list in
                "(5, 3.14)".withCString { buffer in
                    let r = vsscanf(buffer, "(%d, %f)", va_list)
                }
            }
        }
    }
    print(a)
    print(b)
    

    产出

    5
    3.14
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-01-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多