對此的解決方案並不簡單,但也不是不可能。我更願意使用swift包管理器來管理依賴項,並將Xcode作爲IDE進行管理。這種組合並不完美,因爲它需要大量修補,但目前還沒有任何其他可用的免費swift IDE。
您將需要設立兩個項目,我們姑且稱之爲插件(第三方庫)和PluginConsumer(應用程序使用其他人的插件)。您還需要在API決定,現在我們將使用簡單的
TestPluginFunc()
創建Plugin.swift與TestPluginFunc實現文件在您的插件項目:
public func TestPluginFunc() {
print("Hooray!")
}
將項目建設框架,不可執行並生成[1]。你將得到包含你的插件的Plugin.framework文件。
現在切換到你的PluginConsumer項目
複製Plugin.framework從插件項目的地方在那裏,你可以很容易地找到它。要實際加載框架並使用它:
// we need to define how our plugin function looks like
typealias TestPluginFunc = @convention(c)()->()
// and what is its name
let pluginFuncName = "TestPluginFunc"
func loadPlugin() {
let pluginName = "Plugin"
let openRes = dlopen("./\(pluginName).framework/\(pluginName)", RTLD_NOW|RTLD_LOCAL)
if openRes != nil {
// this is fragile
let symbolName = "_TF\(pluginName.utf8.count)\(pluginName)\(initFuncName.utf8.count)\(initFuncName)FT_T_"
let sym = dlsym(openRes, symbolName)
if sym != nil {
// here we load func from framework based on the name we constructed in "symbolName" variable
let f: TestPluginFunc = unsafeBitCast(sym, to: TestPluginFunc.self)
// and now all we need to do is execute our plugin function
f()
} else {
print("Error loading \(realPath). Symbol \(symbolName) not found.")
dlclose(openRes)
}
} else {
print("error opening lib")
}
}
如果操作正確,您應該看到「Hooray!「
有很大的改進空間,你應該做的第一件事是用參數替換Plugin.framework字符串,最好使用一些文件庫(我正在使用PerfectLib)。在您的PluginConsumer項目中定義插件API作爲協議或基類,創建框架,在您的插件項目中導入該框架,並將您的實現基於該協議/基類。我試圖弄清楚如何做。如果我奶源正確做到這一點,我會更新這個帖子
[1]:我通常通過創建Package.swift文件和創建Xcode項目出它使用swift package generate-xcodeproj
的做到這一點。如果你的項目沒有。包含main.sw ift,xcode將創建框架而不是可執行文件