macOS捆绑包之间的双向数据交换(快速) [英] Bidirectional data exchange between macOS Bundles (swift)
问题描述
如何在macOS捆绑包之间传递数据?
How can I pass data between macOS Bundles?
例如:MyApp.app将数据发送到MyBundle.bundle中的函数或类初始化程序,后者执行自己的逻辑在上面。甚至可以返回一个值,然后MyApp.app可以对其进行进一步处理。
eg: MyApp.app sends data to a function or class initialiser in MyBundle.bundle, which performs its own logic on it. It could even return a value, which MyApp.app can then process further.
例如,MyBundle中的一个函数(未嵌套在任何其他声明中):
Fo example, a function in MyBundle (not nested in any other declaration):
void initialise(unsigned int frameCount) {…} // not a class initialiser btw
我已经尝试过:
-
在MyBundle,然后使用
Foundation.Bundle
将其加载到MyApp中:
Declaring a class in MyBundle and then loading it in MyApp using
Foundation.Bundle
:
let class = (Bundle(url: url)!.classNamed("MyClass")! as! NSObject.Type).init()
// class is an instance of NSObject, but I can override the `init()` method
// (in MyBundle) to do whatever. I have not found a way to implement an
// initialiser with parameters, and it still be recognised here.
在MyBundle中声明一个函数并使用 CFBundleGetFunctionPointerForName $ c
Declaring a function in MyBundle and using CFBundleGetFunctionPointerForName
to retrieve it.
var bundles = CFBundleCreateBundlesFromDirectory(kCFAllocatorDefault, bundleDirectory, bundleExtension)! as Array
var bundle1 = bundles.first! as! CFBundle
var untypedFunctionPointer = CFBundleGetFunctionPointerForName(bundle, "initialise" as CFString)!
let imp = unsafeBitCast(untypedFunctionPointer, to: IMP.self)
let function = unsafeBitCast(imp, to: (@convention(c)(CUnsignedInt) -> Void).self)
// If I specify parameters here, pass them in below, then try to use them in my objective c function, I get exc_bad_access.
function(CUnsignedInt(1.0)) // Will work only when not trying to access parameters in the original objective c function.
// Whatever @convention(c) function signature I use, the parameters are unusable in Objective C.
两者的关键问题是我无法将数据作为参数传递。因此,打印语句将起作用,但不能使用参数。
The critical issue with both is that I am unable to pass data in as parameters. So a print statement will work but no ability to use arguments.
编辑:接受的答案显示了调用函数指针的正确方法。我谈论的崩溃是由于使用了无法正确桥接到C语言族的类型而导致的,因此在有疑问时请坚持使用Foundation库中的NSNumber,NSString等。
Edit: Accepted answer shows the correct method for calling function pointers. The crashes I talked about are a result of using types which are not being bridged to the C family of languages properly, so stick to NSNumber, NSString etc. from the Foundation library when in doubt.
推荐答案
根据您的问题从Bundle中调用Swift函数和评论在 https://stackoverflow.com/a/56281093/5329717 中,我想您是在Swift中动态调用函数之后指针或带有 UnsafeBufferPointer
参数的Objective-C方法。
Based on your question Call Swift function from Bundle and comments in https://stackoverflow.com/a/56281093/5329717 I presume you're after dynamically invoking in Swift a function pointer or an objective-c method with UnsafeBufferPointer
argument.
首先 UnsafeBufferPointer
将进行复制,以便进行互操作,我建议改用 OpaquePointer
。
First of all UnsafeBufferPointer
will make a copy so for interoping I recommend switching to OpaquePointer
instead.
假定函数指向带有签名 void cFunction(void * arg)
的指针大小写:
Assuming function to pointer case with signature void cFunction(void* arg)
:
let fakeIMP = unsafeBitCast(functionToPointerAddress, to: IMP.self)
unsafeBitCast(fakeIMP,to:(@convention(c)(OpaquePointer)->Void).self)(bufferArg)
假定静态objective-c方法:
Assuming static objective-c method:
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)
这篇关于macOS捆绑包之间的双向数据交换(快速)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!