Plugins 如何在swift中创建插件
我发现了如何使用Swift和Cocoa创建插件。它使用NSBundle加载插件,但据我所知,这在纯swift中是不可用的(没有Cocoa)。有没有办法在不使用可可粉的情况下达到同样的效果 更多信息:Plugins 如何在swift中创建插件,plugins,swift3,Plugins,Swift3,我发现了如何使用Swift和Cocoa创建插件。它使用NSBundle加载插件,但据我所知,这在纯swift中是不可用的(没有Cocoa)。有没有办法在不使用可可粉的情况下达到同样的效果 更多信息: 如果相关的话,以下是我想要实现的目标。我用在linux服务器上运行的swift创建应用程序。用户可以使用浏览器连接到它。我希望能够让其他人编写“插件”,实现自己的功能(用户连接后可以看到和执行的功能),从打印hello world,通过聊天程序到游戏,而不必担心我的应用程序提供的低级内容。我的服务器
如果相关的话,以下是我想要实现的目标。我用在linux服务器上运行的swift创建应用程序。用户可以使用浏览器连接到它。我希望能够让其他人编写“插件”,实现自己的功能(用户连接后可以看到和执行的功能),从打印hello world,通过聊天程序到游戏,而不必担心我的应用程序提供的低级内容。我的服务器应用程序加载并运行的某种dll 您要做的是创建一个文件夹,让程序在其中查找。比方说它叫“插件”。它应该从其中的文件中创建一个名称列表,然后使用它们进行迭代,将参数传递给文件,获得输出,并以某种方式使用这些文件 : ` 以下是swift插件如何接受参数:
for i in 1..C_ARGC {
let index = Int(i);
let arg = String.fromCString(C_ARGV[index])
switch arg {
case 1:
println("1");
case 2:
println("2")
default:
println("3)
}
}
因此,一旦程序和插件进行了通信,您只需根据输出在程序中添加处理,这样插件输出就可以做一些有意义的事情。如果没有cocoa库,这似乎是一种方法,但是如果使用C,也有一些其他选项可用。希望这有帮助 解决这个问题的方法并不简单,但也不是不可能做到的。我更喜欢使用swift软件包管理器来管理依赖项和作为IDE的Xcode。这种组合并不完美,因为它需要大量的修改,但目前还没有其他可用的免费swift IDE 您将需要设置两个项目,我们将它们称为Plugin(第三方库)和pluginCustomer(使用其他人插件的应用程序)。您还需要决定API,因为现在我们将使用simple
TestPluginFunc()
在您的Plugin项目中创建Plugin.swift文件和TestPluginFunc实现:
public func TestPluginFunc() {
print("Hooray!")
}
将项目设置为生成框架,而不是可执行和生成[1]。您将获得Plugin.framework文件,其中包含您的插件
现在切换到您的pluginumer项目
将Plugin.framework从您的Plugin项目复制到您可以轻松找到它的地方。要实际加载并使用框架,请执行以下操作:
// 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")
}
}
如果操作正确,您应该会看到“万岁!”打印到日志中
还有很大的改进空间,首先应该用参数替换Plugin.framework字符串,最好使用一些文件库(我使用的是PerfectLib)。另一件需要注意的事情是,在PluginConsumer项目中将pluginAPI定义为协议或基类,在此基础上创建框架,在plugin项目中导入该框架,并将实现基于该协议/基类。我正试图弄清楚如何做到这一点。我会更新这篇文章,如果我管理做得好
[1] :我通常通过创建Package.swift文件并使用swift Package generate xcodeproj
从中创建xcode项目来实现这一点。如果您的项目不包含main.swift,xcode将创建框架而不是可执行文件
// 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")
}
}