The way that I have done this in the past is pass a protocol as an unsafe pointer to an exposed entry point: ```swift let entryPoint = dlsym(handle, “initializePlugin”) guard entryPoint != nil else { fatalError("missing plugin entry point: \(pluginPath)") } typealias PluginInitializationFunc = @convention(c) (UnsafeRawPointer) -> () let f = unsafeBitCast(entryPoint, to: PluginInitializationFunc.self) f(Unmanaged.passUnretained(self).toOpaque()) ```
and then in the plugin convert back to the appropriate type: ``` @_cdecl("initializePlugin") public func initializePlugin(_ ptr: UnsafeRawPointer) { let manager = Unmanaged<PluginManager>.fromOpaque(ptr).takeUnretainedValue() ``` HTH, - Daniel > On Oct 4, 2017, at 11:02 AM, Ján Kosa via swift-users <swift-users@swift.org> > wrote: > > Hello folks, > > I have been toying with dynamic libraries, trying to implement plugin > functionality. I was able to get to the point where I can call simple > function in loaded library, but I am having troubles starting more > sophisticated communication channel. > > There are 3 projects > - PluginConsumer is an app that loads plugin libraries > - MyPlugin is a plugin implementation, output is dynamic library that > PluginConsumer loads > - PluginInterface is common interface that both MyPlugin and PluginConsumer > use, so that they know how to communicate > > My first idea was to have PluginInterface be a simple SPM project with single > file where the bare-bones PluginInterface class would be: > > > open class PluginInterface { > > open func sayHi() > > } > > > > Package.swift file: > > > > // swift-tools-version:4.0 > > import PackageDescription > > let package = Package( > > name: "PluginInterface", > > products: [ .library(name: "PluginInterface", type: .dynamic, targets: > ["PluginInterface"]) ], > > targets: [ .target(name: "PluginInterface") ] > > > ) > > > > > > UserPlugin is also very simple project containing only one file: > > > > public func getPlugin() -> AnyObject { > > return MyPlugin() > > > } > > > > class MyPlugin: PluginInterface { > > override func sayHi() { > > print("Hi from my plugin") > > } > > } > > Package.swift: > > > > // swift-tools-version:4.0 > > import PackageDescription > > let package = Package( > > name: "MyPlugin", > > products: [ .library(name: "MyPlugin", type: .dynamic, targets: > ["MyPlugin"]) ], > > dependencies: [ .package(url: "url_to_PluginInterface", from: "0.0.0"), ], > > targets: [ > > .target(name: "PluginInterface", dependencies: ["PluginInterface"]), > > .target(name: "MyPlugin", dependencies: ["PluginInterface"]), > > ] > > > ) > > > > The PluginConsumer is bit more complicated, but here is relevant part (lib > loading and function calling): > > > > typealias InitFunction = @convention(c) () -> AnyObject > > > > let openRes = dlopen(pathToLib, RTLD_NOW|RTLD_LOCAL) > > if openRes != nil { > > defer { > > dlclose(openRes) > > } > > let symbolName = "mangled_symbol_name" > > let sym = dlsym(openRes, symbolName) > > > > if sym != nil { > > let f: InitFunction = unsafeBitCast(sym, to: InitFunction.self) > > let plugin = f() as? PluginInterface > > } > > > } > > Package.swift file: > > // swift-tools-version:4.0 > > import PackageDescription > > let package = Package( > > name: "PluginConsumer", > > dependencies: [ .package(url: "path_to_plugin_interface", from: "0.0.0") > ], > > targets: [ .target(name: "PluginConsumer", dependencies: > ["PluginConsumer"]) ] > > > ) > > > > This all compiles nicely, MyPlugin project creates dylib file that executable > created by PluginConsumer can load, but the problem is with following line: > > let plugin = f() as? PluginInterface > > Type of the plugin is MyPlugin, but from the consumer's view, it doesn't > inherit from PluginInterface so I can't call sayHi() method. I assume this is > because there is no relation between PluginInterface class that compiler uses > for MyPlugin project one that it uses for PluginConsumer project. After > library is loaded, they are two completely different classes that happen to > share same name. Is my assumption correct and how do I go about fixing it? > > I had an idea I could make PluginInterface emit dynamic library that would be > dynamically linked by both MyPlugin and PluginConsumer, thus making them > share same PluginInterface class, but I can't figure out how to do that (or > if it's right way of doing this). > > > > Any help appreciated :) > > Lope > > _______________________________________________ > swift-users mailing list > swift-users@swift.org > https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users