I tried swift package clean, but it didn't help "Try to ensure the plugin provider module (libA) is (only) being compiled into its standalone shared library file." How do I go about this? It is 3rd party module, it doesn't define any products (https://github.com/apple/swift-protobuf.git). Is there something I can do in my Package files to make sure it is loaded dynamically?
On 6 October 2017 at 22:52, Geordie Jay <geo...@gmail.com> wrote: > I think SwiftPM is (incorrectly) compiling A.XYZ into each of the modules > that depend on it, as well as into your intended libA.so file. > > Try to ensure the plugin provider module (libA) is (only) being compiled > into its standalone shared library file. Try cleaning the swiftpm build for > one (swift package clean) and ensure the Package.swift files are correctly > set up to output the shared library. > > Sorry I can’t be more specific, I’ve had these same kinds of issues before > but I’m not 100% what they were. > > Geordie > > > Ján Kosa via swift-users <swift-users@swift.org> schrieb am Fr. 6. Okt. > 2017 um 14:41: > >> It worked! Took me a while to iron out details, but it is working now. >> Huge thanks sir, I will name my firstborn after you. >> Thanks for the @_cdecl("initializePlugin") tip as well, I didn't know >> about it and it will be very useful. >> >> I am having slightly related problem now (it was there before, but I >> ignored it for the time being), not sure if I should start a new thread? >> >> The PluginInterface module has one external dependency on module A, >> PluginConsumer has the dependency on module B which has dependency on same >> module A that the PluginInterface uses. When I load the plugin library, I >> get bunch of errors like: >> >> Class A.XYZ is implemented in both libPluginInterface.dylib and >> libMyPlugin.dylib >> >> I know why it is there, but I don't know how to get rid of it. I can't >> just remove dependency from PluginConsumer and use the one from >> PluginInterface (if that would even work?) because PluginConsumer does not >> depend on it directly, but it is going through module B first >> >> Cheers, >> Lope >> >> On 4 October 2017 at 22:17, Daniel Dunbar <daniel_dun...@apple.com> >> wrote: >> >>> 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 >> >
_______________________________________________ swift-users mailing list swift-users@swift.org https://lists.swift.org/mailman/listinfo/swift-users