首页 > 解决方案 > macOS Bundles 之间的双向数据交换 (swift)

问题描述

如何在 macOS 捆绑包之间传递数据?

例如:MyApp.app 将数据发送到 MyBundle.bundle 中的函数或类初始化程序,后者对其执行自己的逻辑。它甚至可以返回一个值,然后 MyApp.app 可以进一步处理。

例如,MyBundle 中的一个函数(不嵌套在任何其他声明中):

    void initialise(unsigned int frameCount) {…} // not a class initialiser btw

我努力了:

两者的关键问题是我无法将数据作为参数传递。因此,打印语句将起作用,但无法使用参数。

编辑:接受的答案显示了调用函数指针的正确方法。我谈到的崩溃是由于使用了没有正确桥接到 C 语言家族的类型的结果,所以如果有疑问,请坚持使用 Foundation 库中的 NSNumber、NSString 等。

标签: swiftbundlefoundation

解决方案


根据您的问题Call Swift function from Bundle和https://stackoverflow.com/a/56281093/5329717中的评论,我认为您是在 Swift 中动态调用函数指针或带UnsafeBufferPointer参数的 Objective-c 方法之后。

首先UnsafeBufferPointer将制作一个副本,因此为了互操作,我建议OpaquePointer改用。

假设函数指向带有签名的指针大小写void cFunction(void* arg)

let fakeIMP = unsafeBitCast(functionToPointerAddress, to: IMP.self)
unsafeBitCast(fakeIMP,to:(@convention(c)(OpaquePointer)->Void).self)(bufferArg)

假设静态objective-c方法:

let receiverClass = NSClassFromString("SomeClass")
let selector: Selector = NSSelectorFromString("selectorArg:")
let methodIMP: IMP! = method_getImplementation(class_getClassMethod(receiverClass, selector))
unsafeBitCast(methodIMP,to:(@convention(c)(AnyClass?,Selector,OpaquePointer)->Any).self)(receiverClass,selector, bufferArg)

对于您提供的 C 签名

void initialise(unsigned int frameCount);

尝试这个:

let imp = unsafeBitCast(functionToPointerAddress, to: IMP.self)
unsafeBitCast(imp,to:(@convention(c)(Int)->Void).self)(1)

推荐阅读