在 Swift 中使用 const char * 初始化 C-struct

Posted

技术标签:

【中文标题】在 Swift 中使用 const char * 初始化 C-struct【英文标题】:Initializing C-struct with const char * in Swift 【发布时间】:2022-01-17 18:34:06 【问题描述】:

我在库中有以下 C 风格结构:

typedef struct ServiceParam

    const char *name;
    const char *value;
 ServiceParam;

我有兴趣从 Swift 初始化这些结构的数组,这是我尝试过的:

let cHeaders = headers.mapServiceParam(name: $0.name, value: $0.value)

但收到以下警告:

将“字符串”传递给参数,但参数“值”应该是 比对 'init(name:value:)' 的调用寿命更长的指针

namevalue C 参数以UnsafePointer<CChar>! 的形式强制转换,输入类型为(name: String, value: String),即Swift 元组,但我在更改初始类型方面很灵活。

因此,整个最小示例如下所示:

    public func setParams(headers: [(name: String, value: String)] = []) 
        let cHeaders = headers.mapServiceParam(name: $0.name, value: $0.value)
        // Do the work with `cHeaders`
    

从 Swift 调用站点初始化上述 C 样式结构的最佳方法是什么?

ServiceParam 结构仅在父函数调用期间临时使用,但 namevalue 字符串作为 C++ 对存储在数组中,并且它们的生命周期在函数返回后继续:

稍后:

        const auto paramPair = std::make_pair(params->name, params->value);
        instance_variable_array.push_back(paramPair);

【问题讨论】:

ServiceParam 结构的生命周期是多少?它们仅在该功能内使用还是更长?问题是 Swift 字符串的 C 字符串表示只是暂时的。您可能需要复制 C 字符串(并稍后释放该内存)。 更新了我的问题,回答了你的问题。 【参考方案1】:

将 Swift 字符串传递给采用 const char * 参数的 C 函数时,会自动创建一个临时的 C 字符串表示。但是,该 C 字符串仅在函数调用期间有效。这就是发生在

ServiceParam(name: $0.name, value: $0.value)

并导致警告。有一个withCString 方法可用于创建在某些范围内有效的 C 字符串表示:

name.withCString  cName in
    value.withCString  cValue in
        let sp = ServiceParam(name: cName, value: cValue)
        // Do something with sp ...
    

但同样,在执行离开这些范围后,C 字符串指针无效。

为了延长 C 字符串的生命周期,您可以复制内存并在以后释放它:

let cHeaders = headers.map ServiceParam(name: strdup($0.name),
                                         value: strdup($0.value)) 

// Do the work with `cHeaders`

for header in cHeaders 
    free(UnsafeMutablePointer(mutating: header.name))
    free(UnsafeMutablePointer(mutating: header.value))

【讨论】:

您的解决方案“延长 C 字符串的使用寿命”效果很好,谢谢!

以上是关于在 Swift 中使用 const char * 初始化 C-struct的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift 中声明一个静态 const char 数组? [关闭]

const char []和const char之间的区别*

深入理解const char*p,char const*p,char *const p,const char **p,char const**p,char *const*p,char**const p

可以/为啥在返回类型中使用 char * 而不是 const char * 会导致崩溃?

c_cpp 在const char **中使用strtod

在 C# 中使用“const char*”和“const int”编组我的 C++ .dll