从 Swift 调用 C 非常简单,但是我正在研究在 C 中制作双向包装器,所以我的 C 必须调用 Swift 函数。
现在,我可以通过在 C 中声明函数指针,并在 Swift 端将它们设置为在 Swift 中调用代码后让我的 C 函数调用它们来做到这一点。
我的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我可以看看吗?
根据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);
}
你可以这样做:
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];
}
在 C 和 Swift 之间传递值
在C
extern char *mySwiftFunction(char *valuefromc);
int checkSwiftFuncation(void )
{
char *retval = mySwiftFunction("samplevalue");
printf("value %s\n",retval);
return 0;
}
在 Swift 中
@_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!)
}}