【问题标题】:Passing swift string to c function char *将 swift 字符串传递给 c 函数 char *
【发布时间】:2019-09-28 12:13:05
【问题描述】:

我正在尝试将字符串参数从 swift 函数包装器传递给 C 函数,该函数采用 char*。

这是一个 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

【问题讨论】:

    标签: c swift language-interoperability


    【解决方案1】:

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

    long被导入为Int,而在苹果的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)
    }
    

    当函数不保留指针供以后使用时,我更喜欢在将指针传递给 C 函数时使用数组。使用数组,您无需担心解除分配。

    您可以看到代码如何将输入 star 转换为 CChar 数组并将该数组转换回字符串。

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

    【讨论】:

    • 我知道如果我不够快谁会回答这个问题:)
    • 顺便说一句,long 在 32 位和 64 位 (Apple) 平台上都是 Int
    • 一如既往地感谢@MartinR。因此,问题在于 OP 将 Int32 用于最初的 long 参数 iFlg。该库可能是在 long is 32-bit 环境中编写的,这可能会在 64-bit 环境中导致一些问题。
    • @OOPer 可能带来什么样的问题?
    • @John,当您假设 longInt32 并且它正在工作时,该库可能仅适用于 32 位平台。此类库可能无法在 64 位环境中运行。如果确认该库可用于 64 位平台,或者您的代码仅适用于 32 位平台,那可能不是问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-01-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    相关资源
    最近更新 更多