将 Swift 字符串传递给 C

Lou*_*Lou 2 c ios swift

我对 Swift 还是很陌生,而且我对 C 的接触不多。

我正在尝试用 C 编写一个函数,该函数将获得一个 Swift 字符串,然后我可以用它做一些事情。问题是我不能 100% 确定 Swift 中的类型应该是什么才能使 C 看起来像它所看到的那样。

到目前为止,我在 Stack 上找到了几个看起来不错的例子,但对于当前版本的 Swift 来说,有些例子似乎已经过时了。

我首先使用这个例子让 C 和 Swift 相互交谈:Swift call C call Swift? 然后我接受了它并尝试更新 Swift 函数以返回某种字符串。我知道它需要是 UTF-8 返回类型,但我不确定如何正确发送内容。我看过如何将 Swift 字符串传递给 ac 函数?如何将 String 转换为 UnsafePointer<UInt8> 和 length,以及如何在 Swift 中将字符串转换为 unicode(UTF-8) 字符串?,但它们中没有一个真正适用于解决方案。或者我只是输入错误。到目前为止,我最接近返回的东西如下。

在 Swift 中,我ViewController是:

import UIKit

class ViewController: UIViewController {

    @_silgen_name("mySwiftFunc") // give the function a C name
    public func mySwiftFunc(number: Int) -> [CChar]
    {
        print("Hello from Swift: \(number)")

        let address: String = "hello there";
        let newString = address.cString(using: String.Encoding.utf8)
        return newString!
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.

        blah()

    }
}
Run Code Online (Sandbox Code Playgroud)

在 C 中,标题是这样的:

#ifndef cfile_h
#define cfile_h

#include <stdio.h>

const char * mySwiftFunc(int);
int blah(void);

#endif /* cfile_h */
Run Code Online (Sandbox Code Playgroud)

来源是这样的:

#include "cfile.h"

int blah() {

    const char * retVal = mySwiftFunc(42); // call swift function
    printf("Hello from C: %s", retVal);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

有一个桥接头文件,只有#include "cfile.h". 显然,第一个例子中还有很多残留物,这些将在以后清理。

需要改变什么才能使这项工作?现在,控制台吐出

Hello from Swift: 42
Hello from C: (B\214
Run Code Online (Sandbox Code Playgroud)

Mar*_*n R 6

Swift 等价于const char *is UnsafePointer<CChar>?,所以这是正确的返回值。然后你必须考虑内存管理。一种选择是在 Swift 函数中为 C 字符串分配内存,并将其留给调用者最终释放内存:

public func mySwiftFunc(number: Int) -> UnsafePointer<CChar>? {
    print("Hello from Swift: \(number)")

    let address = "hello there"
    let newString = strdup(address)
    return UnsafePointer(newString)
}
Run Code Online (Sandbox Code Playgroud)

将 Swift 字符串传递给,strdup()以便自动创建(临时)C 字符串表示。然后复制这个 C 字符串。调用 C 函数必须在不再需要该内存时释放该内存:

int blah() {
    const char *retVal = mySwiftFunc(42);
    printf("Hello from C: %s\n", retVal);
    free((char *)retVal);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

?? 但是:请注意,您的代码中存在更多问题:

  • mySwiftFunc()是类的实例方法,因此具有隐式self参数,调用 C 函数会忽略该参数。这可能是偶然的,或者导致奇怪的失败。
  • @_silgen_name不应该是雨燕标准库的使用外,看到这discusssion在斯威夫特论坛。
  • 一个稍微好一点的选择是,@_cdecl但即使这样也没有得到官方支持。@_cdecl只能与全局函数一起使用。
  • 通常,官方不支持直接从 C 调用 Swift 函数,有关原因和可能的替代方案请参阅Swift 论坛中的此讨论


归档时间:

查看次数:

511 次

最近记录:

6 年,6 月 前