Swift:创建指针数组以调用 C 函数

标签 swift pointers memory

上下文

我试图从 Swift 调用 libxlsxwriter C 库的特定函数。文档在这里:https://libxlsxwriter.github.io/worksheet_8h.html#a62bf44845ce9dcc505bf228999db5afa

该函数组装一个“丰富的字符串”(相​​当于一个 AttributedString,其中不同的格式/样式适用于不同的范围)并将其写入 Excel 工作表中的特定单元格。在 C 中,该函数的工作方式如下:

lxw_format *bold = workbook_add_format(workbook);
format_set_bold(bold);
 
lxw_format *italic = workbook_add_format(workbook);
format_set_italic(italic);
 
lxw_rich_string_tuple fragment11 = {.format = NULL,   .string = "This is "     };
lxw_rich_string_tuple fragment12 = {.format = bold,   .string = "bold"         };
lxw_rich_string_tuple fragment13 = {.format = NULL,   .string = " and this is "};
lxw_rich_string_tuple fragment14 = {.format = italic, .string = "italic"       };
 
lxw_rich_string_tuple *rich_string1[] = {&fragment11, &fragment12,
                                         &fragment13, &fragment14, NULL};
 
worksheet_write_rich_string(worksheet, CELL("A1"), rich_string1, NULL);

问题

我有一个 lxw_rich_string_tuple 结构数组,但我不清楚如何将其转换为 worksheet_write_rich_string() 接受的指针数组:


// The worksheet object and `lxw_format` objects are already existent. 
// This array contains multiple well-formed `lxw_rich_string_tuple` structs, which I can see in the debugger.
//
var rawTuples: [lxw_rich_string_tuple] =  ...


// Parameters: 
//    - the worksheet on which to write this string
//    - the row of the cell in which to write
//    - the column of the cell in which to write
//    - a null-terminated array of pointers to `lxw_rich_string_tuple` structs
//    - an optional format object to use, null in this case.
//
worksheet_write_rich_string(worksheet, 0, 1, ?, NULL);

麻烦是 ?。我已经尝试了各种 withUnsafeByteswithUnsafeMutableBytesUnsafeMutableRawPointer().bindMemory(to:capacity:) 我无法弄清楚魔法在 C 中做如此简单的事情的 Swift 乱码。谢谢。

我的尝试

这不会产生编译器错误,但会因错误访问异常而崩溃:

let argsSize: Int = rawTuples.count

rawTuples.withUnsafeMutableBufferPointer { rawTuplesPointer in

    let ptr = UnsafeMutableRawPointer(rawTuplesPointer.baseAddress!).bindMemory(to: lxw_rich_string_tuple.self, capacity: argsSize)
    var tuplePointers: [UnsafeMutablePointer<lxw_rich_string_tuple>?] = []

    for i in 0 ..< argsSize
    {
        let tp: UnsafeMutablePointer<lxw_rich_string_tuple>? = ptr + (i * MemoryLayout<lxw_rich_string_tuple>.stride)           
        tuplePointers.append(tp)
    }
    tuplePointers.append(nil)

    tuplePointers.withUnsafeBufferPointer { tpPointer in

        let m = UnsafeMutablePointer(mutating: tpPointer.baseAddress)
        worksheet_write_rich_string(lxw_worksheet, cell.row, cell.col, m, nil)

    }
}

最佳答案

试试这个:

rawTuples.withUnsafeMutableBufferPointer { p in
    guard let arrBaseAddress = p.baseAddress else { return }

    var pointersToEachArrayElement: [UnsafeMutablePointer<_>?] = 
        Array(arrBaseAddress ..< arrBaseAddress.advanced(by: p.count))
    pointersToEachArrayElement.append(nil)
    pointersToEachArrayElement.withUnsafeMutableBufferPointer { q in
        // use q.baseAddress in the call to worksheet_write_rich_string
    }
}

这个想法类似于您的尝试 - 创建一个指向每个数组元素的指针数组。但与您的尝试不同,我避免调用指针类型的初始化程序(我认为您不应该这样做),而是尽可能多地尝试使用 withXXX 函数。

您还应该考虑仅围绕 C 函数和 lxw_rich_string_tuple 编写 Objective-C 包装器。有时 C 函数并没有以非常方便的方式桥接到 Swift 中,并且 this is not the first time I've experienced something like this,不幸的是:(

关于Swift:创建指针数组以调用 C 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73509502/

相关文章:

c - 在 C 中操作字符串的两种方式有什么区别?

matlab - 如何在 MATLAB 中将指针分配给对象的属性?

c++ - 如何寻址使用 36 位映射的 IO?

检索大数据库记录 (~5MB) 时 PHP(或 MySQL)崩溃

swift - 如何将从用户处获取的文本添加到图像中?

ios - 无法将类型 'Array<AboutMe>' 的返回表达式转换为返回类型 '[About me]'

ios - 调整 UITableViewCell 的高度

ios - 如何设置自动布局约束常数通用或设备特定?

c - 二维数组和指针有什么关系?

r - 在大型数据框中生成指标