Context

在SWIFT中,我正在try 调用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);

The Problem

我有一个由lxw_rich_string_tuple个 struct 组成的数组,但我不清楚如何将其转换为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:),但我想不出Swift 的胡言乱语怎么能在C中做这么简单的事情.谢谢.

My Attempt

这不会产生编译器错误,但会崩溃,并出现错误访问异常:

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
    }
}

这个 idea 与您的try 类似--创建一个指向每个数组元素的指针array.但与您的try 不同,我避免调用指针类型的初始值设定项(我认为您不应该这样做),而是try 尽可能多地使用withXXX个函数.

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

Swift相关问答推荐

try 在SwiftUI中做5星评级

SwiftUI轨迹绘制怪异

如何在SWIFT任务中判断当前任务是否已取消(异步/等待)

SWIFT异步/等待,多个监听程序

从SwiftUI使用UIPageView时,同一页面连续显示两次的问题

TimeZone 背后的目的

可以将属性名称传递给 Swift 中的函数吗?

在SwiftUI中使用ForEach循环来显示字典项的键和值在Form视图中

在SwiftUI中如何预览嵌套的ScrollView,以避免触发可刷新修饰符

DispatchQueue.main.asyncAfter 等同于 Swift 中的 struct 化并发?

NavigationStack 和 TabView - 工具栏和标题不显示

如何避免从模块导入函数

不要从 NumberFormatter 获取货币符号

如何在 SwiftUI 中通过按钮点击一次为一个更改设置动画?

在 Swift 中获取双精度的小数部分

如何在 Swift 中复制字典?

CMutablePointer - 如何访问它?

如何在 Swift 中将 UILabel 居中?

使用 DispatchTime.now() + float 延迟?

Swift 2.0 最低系统版本要求(部署目标)