我遇到一个涉及访问外部库的类实例的问题,该外部库本身使用全局变量,并且可以作为单例访问。因此,我希望/必须为每个swift类实例加载一个dylib实例。 让我提前说明一下:这是我在这里的第一篇文章,如果它的质量与观众不符,我道歉。随意纠正我。
应用程序的背景如下:我正在开发一个框架包,它又使用安装在bundle ./Frameworks文件夹中的dylib中的一些函数。 dylib及其依赖项是用Fortran编写的,用gfortran编译。我已经成功实现并测试了dylib对象的c头,用它们创建了一个模块映射,我能够访问fortran函数并在我的swift类中使用它们(在所有地方传递不安全的指针)。架构如下: myClass.swift - > fortranLib.dylib - > (libgfortran.dylib,libquadmath.dylib)
我遇到的问题是:fortranLib.dylib的实现是一种非常典型的fortran方式 - 它使用全局变量和嵌套函数调用,因此从myClass的多个实例调用它是完全不安全的。当我有一个实例并使用setup_(某些指针)例程初始化fortran库时,一切都按预期工作。一旦我创建myClass的第二个实例并尝试从第二个实例调用setup_()和其他函数,奇怪的事情就会开始发生。这对我来说当然是完全合乎逻辑的:myClass的快速实例都试图访问相同的库函数,不知道库的全局变量和内部交互。
我的问题是:如何通过为myClass的每个实例加载一个全新的fortranLib.dylib来解决这个问题,就像实例和库是独立的内存包一样?
提前谢谢!
答案 0 :(得分:0)
我想添加我当前的实现,以防它帮助某人。我还没有找到任何方法来加载dlopen或类似的dylibs。
所以我目前的迅速实施如下:
public class MyClass {
// I create a serial queue for the fortran calls
// to ensure that they all execute in sequence
private static let serialFortranQueue = dispatch_queue_create("someName", DISPATCH_QUEUE_SERIAL)
internal let uuid = NSUUID().UUIDString // each instance get's an unique id
internal static var lastUuid = String() // and the last id to access the fortran library is saved
// all pointers to fortran are declared in the instance
private var someP:UnsafeMutablePointer<Int32> = UnsafeMutablePointer<Int32>.alloc(1)
deinit() {
// destroy and dealloc all pointers here
someP.destroy(); someP.dealloc(1)
}
internal static func SetupLibrary(callerID:String) {
// setup the library only if it isn't for the current caller
if callerID == lastUuid {return}
// if not setup the instance
fortranSetupCall_(someOtherP)
lastUuid = callerID
}
public func myFunction() {
// prepare the pointers
someP.memory = 1
// here the fortran calls are executed in the dispatch queue
// so that there is no risk of simultaneous access
dispatch_sync(MyClass.serialFortranQueue) {
MyClass.SetupLibrary(self.uuid)
myFortranFunc_(someP)
}
// evaluate return pointers, etc.
}
}