将快速字符串传递给c函数char *

时间:2019-05-10 14:52:47

标签: c swift language-interoperability

我试图将字符串参数从swift函数包装器传递给采用char *的C函数。

这是一个c函数

long swe_fixstar2_ut(char* star, double tjd_ut, long iflag, double* xx, char* serr);

参数star必须至少提供41个字符作为返回的星形名称。如果找到星星,则返回其名称。此功能从txt文件中搜索星级名称。

当导入到Swift函数时,看起来像这样

swe_fixstar_ut(star: UnsafeMutablePointer<Int8>!, tjd_ut: Double, iflag: int32,
                xx: UnsafeMutablePointer<Double>!, serr: UnsafeMutablePointer<Int8>!)

我想实现这样的目标

public func sweFixStarsUT(star: String, tjdUT: Double, iFlag: Int32) {
      let xx: UnsafeMutablePointer = UnsafeMutablePointer<Double>.allocate(capacity:6)
      let serr:UnsafeMutablePointer = UnsafeMutablePointer<CChar>.allocate(capacity:256)
      swe_fixstar_ut(star, tjdUT, iFlag, xx, serr)
}

我环顾了几个类似的问题,但这并不能解决我的问题。

Convert a Swift Array of String to a to a C string array pointer

How to pass an array of Swift strings to a C function taking a char ** parameter

实际上,此功能来自瑞士星历C库。如果您有兴趣看的话,这里是链接

https://www.astro.com/swisseph/swephprg.htm#_Toc505244846

1 个答案:

答案 0 :(得分:2)

据我阅读文档,参数star用于输入和输出,因此您的Swift函数的star应该是inout

然后将long导入为Int,并且在Apple的64位平台中,它表示64位有符号整数类型,如果实际上是32位,则可能需要更新源您的C代码文件。我认为它是Int

因此,我将这样编写桥接代码:

public func sweFixStarsUT(star: inout String, tjdUT: Double, iFlag: Int) {
    let starLen = max(star.utf8.count, 41)
    var starBuf: [CChar] = Array(repeating: 0, count: starLen+1)
    strcpy(&starBuf, star)
    var xx: [Double] = Array(repeating: 0.0, count: 6)
    var serr: [CChar] = Array(repeating: 0, count: 256)
    swe_fixstar2_ut(&starBuf, tjdUT, iFlag, &xx, &serr)
    star = String(cString: starBuf)
}

当函数的指针不保留指针供以后使用时,我更喜欢使用数组。使用数组,您无需担心分配问题。

您可以看到代码是如何将输入star转换为CChar数组并将其覆盖回String的。

如果您发现此代码有问题,请告诉我。