swift:按类实例加载动态库(或线程安全)

swift:按类实例加载动态库(或线程安全),swift,fortran,dylib,Swift,Fortran,Dylib,我遇到了一个问题,涉及到访问外部库的类实例,外部库本身使用全局变量,并且应该作为单例访问。因此,我希望/必须为每个swift类实例加载一个dylib实例。 让我提前声明一下:这是我在这里的第一篇帖子,如果它的质量与读者不符,我道歉。请随意纠正我 该应用程序的背景如下:我正在开发一个框架捆绑包,它反过来使用安装在捆绑包的./Frameworks文件夹中的动态库中的一些函数。动态库及其依赖项是用Fortran编写的,并用gfortran编译。我已经成功地实现并测试了dylib对象的c头文件,用它们创

我遇到了一个问题,涉及到访问外部库的类实例,外部库本身使用全局变量,并且应该作为单例访问。因此,我希望/必须为每个swift类实例加载一个dylib实例。 让我提前声明一下:这是我在这里的第一篇帖子,如果它的质量与读者不符,我道歉。请随意纠正我

该应用程序的背景如下:我正在开发一个框架捆绑包,它反过来使用安装在捆绑包的./Frameworks文件夹中的动态库中的一些函数。动态库及其依赖项是用Fortran编写的,并用gfortran编译。我已经成功地实现并测试了dylib对象的c头文件,用它们创建了一个模块映射,并且我能够访问fortran函数,并在我的swift类中使用它们(到处传递不安全的指针)。模式如下: myClass.swift->fortranLib.dylib->(libgfortran.dylib,libquadmath.dylib)

我遇到的问题是:fortranLib.dylib的实现是以一种非常典型的fortran方式实现的——它使用全局变量和嵌套函数调用,因此从myClass的多个实例调用它是完全不安全的。当我有一个实例并用它的setup(一些指针)例程初始化fortran库时,一切都按预期工作。当我创建myClass的第二个实例并尝试从该第二个实例调用setup_389;()和其他函数时,奇怪的事情就开始发生了。这对我来说当然是完全合乎逻辑的:myClass的两个swift实例都试图访问相同的库函数,对库的全局变量和内部交互一无所知

我的问题是:如何通过为myClass的每个实例加载一个新的fortranLib.dylib来解决这个问题,就像实例和库是独立的内存包一样


提前谢谢你

我想添加我当前的实现,以防它对某人有所帮助。我还没有找到用dlopen或类似的方法加载dylibs
因此,我当前的swift实现如下:

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.
   }
}
公共类MyClass{
//我为fortran调用创建了一个串行队列
//以确保它们都按顺序执行
私有静态let serialFortranQueue=dispatch\u queue\u create(“someName”,dispatch\u queue\u SERIAL)
内部let uuid=nsuid().UUIDString//每个实例都有一个唯一的id
内部静态变量lastUuid=String()//保存访问fortran库的最后一个id
//所有指向fortran的指针都在实例中声明
私有变量someP:UnsafeMutablePointer=UnsafeMutablePointer.alloc(1)
脱硝剂(){
//在这里销毁并解除锁定所有指针
someP.destroy();someP.dealloc(1)
}
内部静态函数设置库(callerID:String){
//仅当库不适用于当前调用方时才设置库
如果callerID==lastUuid{return}
//如果没有,请设置实例
fortranSetupCall_u2;(其他人)
lastUuid=callerID
}
公共函数myFunction(){
//准备好指针
someP.memory=1
//在这里,fortran调用在调度队列中执行
//这样就不存在同时访问的风险
调度同步(MyClass.serialFortranQueue){
MyClass.SetupLibrary(self.uuid)
myFortranFunc(someP)
}
//评估返回指针等。
}
}

我想添加我当前的实现,以防它对某人有所帮助。我还没有找到用dlopen或类似的方法加载dylibs
因此,我当前的swift实现如下:

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.
   }
}
公共类MyClass{
//我为fortran调用创建了一个串行队列
//以确保它们都按顺序执行
私有静态let serialFortranQueue=dispatch\u queue\u create(“someName”,dispatch\u queue\u SERIAL)
内部let uuid=nsuid().UUIDString//每个实例都有一个唯一的id
内部静态变量lastUuid=String()//保存访问fortran库的最后一个id
//所有指向fortran的指针都在实例中声明
私有变量someP:UnsafeMutablePointer=UnsafeMutablePointer.alloc(1)
脱硝剂(){
//在这里销毁并解除锁定所有指针
someP.destroy();someP.dealloc(1)
}
内部静态函数设置库(callerID:String){
//仅当库不适用于当前调用方时才设置库
如果callerID==lastUuid{return}
//如果没有,请设置实例
fortranSetupCall_u2;(其他人)
lastUuid=callerID
}
公共函数myFunction(){
//准备好指针
someP.memory=1
//在这里,fortran调用在调度队列中执行
//这样就不存在同时访问的风险
调度同步(MyClass.serialFortranQueue){
MyClass.SetupLibrary(self.uuid)
myFortranFunc(someP)
}
//评估返回指针等。
}
}