Ján Kosa <lope...@gmail.com> schrieb am Sa. 7. Okt. 2017 um 13:34: > 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? >
When you compile a package depending on protobuf, all the relevant symbols end up in your package’s library file. So here’s something you might try: import protobuf into your own “PluginProvider” module (package), which has a shared library product like this: ‘@_exported import Protobuf’ in some compiled swift file. Then from the other dependent modules “import PluginProvider” - the protobuf symbols should be available, and all from one (nonconflicting) source. Geordie > 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