从 C 调用 Swift 的最佳方法是啥?

Posted

技术标签:

【中文标题】从 C 调用 Swift 的最佳方法是啥?【英文标题】:What is the best way to call into Swift from C?从 C 调用 Swift 的最佳方法是什么? 【发布时间】:2016-05-08 11:06:50 【问题描述】:

从 Swift 调用 C 非常简单,但是我正在考虑在 C 中创建一个双向包装器,因此我的 C 必须调用 Swift 函数。

现在,我可以通过在 C 中声明函数指针来做到这一点,并让我的 C 函数在 Swift 端将它们设置为调用 Swift 中的代码后调用它们。

我的 C 头文件:

typedef void (*callback_t)(void);

void callBackIntoSwift( callback_t cb );

我的 C 实现文件:

#include "stuff.h"
#include <stdio.h>

void callBackIntoSwift( callback_t cb )

    printf( "Will call back into Swift\n" );
    cb();
    printf( "Did call back into Swift\n" );

在桥接头中包含我的 C 头文件后,我可以在 Swift 端执行以下操作:

let cb: callback_t = 
    someKindOfSwiftFunction()


callBackIntoSwift( cb )

甚至:

callBackIntoSwift 
    someKindOfSwiftFunction()

有没有更好的方法来做到这一点,不需要函数指针和回调?我想让 C 端直接调用 someKindOfSwiftFunction……但是当我尝试将 @convention (c) 应用于函数声明时,我收到消息,该属性只能应用于类型,而不是声明。

任何想法或代码库,例如Github我可以看看吗?

【问题讨论】:

【参考方案1】:

你可以这样做:

FileSwift.swift

public class SwiftTest: NSObject 
    @objc public static func testMethod() 
        print("Test")
    

FileSwiftWrapper.h

void SwiftFunctionWrapper();

FileSwiftWrapper.m

#import "ProductModuleName-Swift.h"

void SwiftFunctionWrapper() 
      [SwiftTest testMethod];

【讨论】:

OP 询问如何快速调用 C 函数,而不是如何调用 Objective-C 方法 作者想从 C 调用 Swift 代码。“从 Swift 调用 C 非常简单,但是我正在考虑在 C 中创建一个双向包装器,所以我的 C 必须调用 Swift 函数。” @pbush25 也许我可以扩展我的评论。 SwiftFunctionWrapper()函数可以从任何c文件中调用。 @Rolan 是对的……这样做虽然需要额外的包装层以通过 Objective-C 将 C 桥接到 Swift……使用回调至少跳过了该层。那里可能有一些好的资源?【参考方案2】:

根据Joe Groff:

目前还没有正式的方法。除了名称修改之外,Swift 函数使用与 C 不同的调用约定。非正式地,如果您愿意处理比通常数量更多的代码损坏和编译器错误,那么有一个非正式属性 @_cdecl 可以做到这一点:

@_cdecl("mymodule_foo")
func foo(x: Int) -> Int 
  return x * 2

然后你可以从 C 调用它:

#include <stdint.h>

intptr_t mymodule_foo(intptr_t);

intptr_t invoke_foo(intptr_t x) 
  return mymodule_foo(x);

【讨论】:

虽然这个答案是正确的,但我在让事情正常工作时遇到了一些麻烦。 That's why I made a little article.【参考方案3】:

在 C 和 Swift 之间传递值

在 C 中

 extern char *mySwiftFunction(char *valuefromc);
 int checkSwiftFuncation(void )
 
        char  *retval = mySwiftFunction("samplevalue");
        printf("value %s\n",retval);
        return 0;

在斯威夫特中

@_silgen_name("mySwiftFunction")  // vital for the function being visible from C
 func mySwiftFunction(valuefromc: UnsafePointer<Int8>) -> UnsafeMutablePointer<Int8>


    let value = String(cString: valuefromc, encoding: .utf8)
    print ("mySwiftFUnction called in Swift with \(value!)")
    let retmsg = "return message"
    return retmsg.charpointer




extension String 
    var charpointer: UnsafeMutablePointer<Int8> 
        return UnsafeMutablePointer(mutating: (self as NSString).utf8String!)
    

【讨论】:

以上是关于从 C 调用 Swift 的最佳方法是啥?的主要内容,如果未能解决你的问题,请参考以下文章

从单个服务多次调用多个微服务的最佳方法或设计模式是啥?

在linux下用c ++ ping的最佳方法是啥?

从 C# 调用 QuantLib 方法的最佳方法是啥

从 Java 调用 VB.NET 函数的最佳方法是啥?

从 URLRequestConvertible 扩展时设置多部分请求的最佳方法是啥

当我已经返回一个值时,从函数返回错误的最佳方法是啥?