加载用 Vala 编写并使用介子构建的 libpeas 模块失败
Loading a libpeas module written in Vala and built with meson fails
我试图在介子的帮助下构建这个例子:
Getting started with libpeas extensions in vala
我的 meson.build 如下所示:
vala_deps = [
dependency('gio-2.0', version: '>= 2.50'),
dependency('gtk+-3.0', version: '>= 3.22'),
]
libpeas_dep = dependency('libpeas-1.0')
libfoo_deps = [vala_deps, libpeas_dep]
libfoo = shared_library(
'foo',
'window.vala',
vala_header: 'foo.h',
dependencies: libfoo_deps,
install: true,
)
libfoo_dep = declare_dependency(
link_with: libfoo,
dependencies: libfoo_deps,
include_directories: include_directories('.'),
)
extension_deps = [vala_deps, libpeas_dep]
extension = shared_library(
'extension',
'extension.vala',
vala_header: 'extension.h',
dependencies: [vala_deps, libpeas_dep, libfoo_dep],
install: true,
#install_dir : '/app/bin'
)
extension_dep = declare_dependency(
link_with: extension,
dependencies: extension_deps,
include_directories: include_directories('.'),
)
gnome = import('gnome')
extension_resources = gnome.compile_resources(
'extension-resources',
'extension.gresource.xml',
c_name: 'extension',
)
foo_sources = [
'main.vala',
extension_resources[0],
]
foo = executable(
'foo',
foo_sources,
link_with: extension,
#objects: 'libextension.so',
dependencies: [vala_deps, libfoo_dep, extension_dep],
install: true,
)
如果我在 foo = executable(
中使用预编译的共享对象文件 objects: 'libextension.so',
,则该示例有效,如果我不使用,则无效。
有什么建议吗?
编辑:
涉及的文件内容如下:
extension.gresource.xml:
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Foo/plugins">
<file>extension.plugin</file>
</gresource>
</gresources>
extension.plugin:
[Plugin]
Name=extension
Module=extension
Embedded=peas_register_types
extension.vala:
class ValaExtension : Object, Foo.Extension {
public Foo.Window window { get; construct set; }
Gtk.Button button;
void activate() {
button = new Gtk.Button.with_label("Say Hello");
button.clicked.connect(() => {
button.set_label("Hello World!");
});
window.buttons.add(button);
button.show();
}
void deactivate() {
window.buttons.remove(button);
}
}
[ModuleInit]
public void peas_register_types(TypeModule module) {
var objmodule = module as Peas.ObjectModule;
objmodule.register_extension_type(typeof (Foo.Extension), typeof (ValaExtension));
}
main.vala:
int main (string[] args) {
var app = new Gtk.Application ("org.gnome.Foo", ApplicationFlags.FLAGS_NONE);
app.activate.connect (() => {
var win = app.active_window;
if (win == null) {
win = new Foo.Window (app);
}
win.present ();
});
return app.run (args);
}
window.vala:
namespace Foo {
public class Window : Gtk.Window {
public Gtk.ButtonBox buttons { get; set; }
private Peas.ExtensionSet extensions { get; set; }
public Window(Gtk.Application app) {
Object(application: app);
this.buttons = new Gtk.ButtonBox(Gtk.Orientation.VERTICAL);
this.destroy.connect(Gtk.main_quit);
var engine = Peas.Engine.get_default();
engine.add_search_path("/app/lib", null);
engine.prepend_search_path("resource:///org/gnome/Foo/plugins/", null);
extensions = new Peas.ExtensionSet(engine, typeof (Foo.Extension), "window", this);
extensions.extension_added.connect((info, extension) => {
(extension as Foo.Extension).activate();
});
extensions.extension_removed.connect((info, extension) => {
(extension as Foo.Extension).deactivate();
});
foreach (var plugin in engine.get_plugin_list())
engine.try_load_plugin(plugin);
this.add(buttons);
this.show_all();
}
}
public interface Extension : Object {
public abstract Window window { get; construct set; }
public abstract void activate();
public abstract void deactivate();
}
}
如果我评论 objects:'libextension.so'
行,我会收到以下错误:
(foo:2): libpeas-WARNING **: 20:27:31.400: Failed to get 'peas_register_types' for module 'extension': 'peas_register_types': foo: undefined symbol: peas_register_types
(foo:2): libpeas-WARNING **: 20:27:31.400: Error loading plugin 'extension'
已解决:
如果我添加一个虚拟函数:
public void extension_init ()
{
}
到 extension.vala 并从 main.vala 调用它链接适用于 嵌入式 插件,另见此处:gnome_builder_plugins_init.c
objects: 'libextension.so'
会将 link 对象直接放入可执行文件中。从示例中看,您似乎正在使用 libpeas 在 运行 时间加载模块。因此,通过将模块构建到可执行文件中,我假设您在 运行time.
加载模块时遇到问题
本教程还建议设置 LD_LIBRARY_PATH
以包含带有扩展名的目录,并且还有一个 libpeas .plugin
文件。这可能是问题所在。如果您列出错误消息或无法正常工作的详细信息,将会有所帮助。
顺便说一句,使用来自介子构建目标的对象可能更好objects: extension.extract_objects()
,这样对象的名称就不会硬编码到构建中。参见 build target object。 objects:
的使用主要用于测试。
更新
我认为你在extension.plugin
中的模块名称应该是extension.so
。我也喜欢明确说明模块加载器,所以我过去使用过 Loader=C
。我以前没遇到过 Embedded
。所以我会尝试这个作为我的 extension.plugin
:
[Plugin]
Name=My first libpeas extension
Module=extension.so
Loader=C
我试图在介子的帮助下构建这个例子: Getting started with libpeas extensions in vala
我的 meson.build 如下所示:
vala_deps = [
dependency('gio-2.0', version: '>= 2.50'),
dependency('gtk+-3.0', version: '>= 3.22'),
]
libpeas_dep = dependency('libpeas-1.0')
libfoo_deps = [vala_deps, libpeas_dep]
libfoo = shared_library(
'foo',
'window.vala',
vala_header: 'foo.h',
dependencies: libfoo_deps,
install: true,
)
libfoo_dep = declare_dependency(
link_with: libfoo,
dependencies: libfoo_deps,
include_directories: include_directories('.'),
)
extension_deps = [vala_deps, libpeas_dep]
extension = shared_library(
'extension',
'extension.vala',
vala_header: 'extension.h',
dependencies: [vala_deps, libpeas_dep, libfoo_dep],
install: true,
#install_dir : '/app/bin'
)
extension_dep = declare_dependency(
link_with: extension,
dependencies: extension_deps,
include_directories: include_directories('.'),
)
gnome = import('gnome')
extension_resources = gnome.compile_resources(
'extension-resources',
'extension.gresource.xml',
c_name: 'extension',
)
foo_sources = [
'main.vala',
extension_resources[0],
]
foo = executable(
'foo',
foo_sources,
link_with: extension,
#objects: 'libextension.so',
dependencies: [vala_deps, libfoo_dep, extension_dep],
install: true,
)
如果我在 foo = executable(
中使用预编译的共享对象文件 objects: 'libextension.so',
,则该示例有效,如果我不使用,则无效。
有什么建议吗?
编辑:
涉及的文件内容如下:
extension.gresource.xml:
<?xml version="1.0" encoding="UTF-8"?>
<gresources>
<gresource prefix="/org/gnome/Foo/plugins">
<file>extension.plugin</file>
</gresource>
</gresources>
extension.plugin:
[Plugin]
Name=extension
Module=extension
Embedded=peas_register_types
extension.vala:
class ValaExtension : Object, Foo.Extension {
public Foo.Window window { get; construct set; }
Gtk.Button button;
void activate() {
button = new Gtk.Button.with_label("Say Hello");
button.clicked.connect(() => {
button.set_label("Hello World!");
});
window.buttons.add(button);
button.show();
}
void deactivate() {
window.buttons.remove(button);
}
}
[ModuleInit]
public void peas_register_types(TypeModule module) {
var objmodule = module as Peas.ObjectModule;
objmodule.register_extension_type(typeof (Foo.Extension), typeof (ValaExtension));
}
main.vala:
int main (string[] args) {
var app = new Gtk.Application ("org.gnome.Foo", ApplicationFlags.FLAGS_NONE);
app.activate.connect (() => {
var win = app.active_window;
if (win == null) {
win = new Foo.Window (app);
}
win.present ();
});
return app.run (args);
}
window.vala:
namespace Foo {
public class Window : Gtk.Window {
public Gtk.ButtonBox buttons { get; set; }
private Peas.ExtensionSet extensions { get; set; }
public Window(Gtk.Application app) {
Object(application: app);
this.buttons = new Gtk.ButtonBox(Gtk.Orientation.VERTICAL);
this.destroy.connect(Gtk.main_quit);
var engine = Peas.Engine.get_default();
engine.add_search_path("/app/lib", null);
engine.prepend_search_path("resource:///org/gnome/Foo/plugins/", null);
extensions = new Peas.ExtensionSet(engine, typeof (Foo.Extension), "window", this);
extensions.extension_added.connect((info, extension) => {
(extension as Foo.Extension).activate();
});
extensions.extension_removed.connect((info, extension) => {
(extension as Foo.Extension).deactivate();
});
foreach (var plugin in engine.get_plugin_list())
engine.try_load_plugin(plugin);
this.add(buttons);
this.show_all();
}
}
public interface Extension : Object {
public abstract Window window { get; construct set; }
public abstract void activate();
public abstract void deactivate();
}
}
如果我评论 objects:'libextension.so'
行,我会收到以下错误:
(foo:2): libpeas-WARNING **: 20:27:31.400: Failed to get 'peas_register_types' for module 'extension': 'peas_register_types': foo: undefined symbol: peas_register_types
(foo:2): libpeas-WARNING **: 20:27:31.400: Error loading plugin 'extension'
已解决:
如果我添加一个虚拟函数:
public void extension_init ()
{
}
到 extension.vala 并从 main.vala 调用它链接适用于 嵌入式 插件,另见此处:gnome_builder_plugins_init.c
objects: 'libextension.so'
会将 link 对象直接放入可执行文件中。从示例中看,您似乎正在使用 libpeas 在 运行 时间加载模块。因此,通过将模块构建到可执行文件中,我假设您在 运行time.
本教程还建议设置 LD_LIBRARY_PATH
以包含带有扩展名的目录,并且还有一个 libpeas .plugin
文件。这可能是问题所在。如果您列出错误消息或无法正常工作的详细信息,将会有所帮助。
顺便说一句,使用来自介子构建目标的对象可能更好objects: extension.extract_objects()
,这样对象的名称就不会硬编码到构建中。参见 build target object。 objects:
的使用主要用于测试。
更新
我认为你在extension.plugin
中的模块名称应该是extension.so
。我也喜欢明确说明模块加载器,所以我过去使用过 Loader=C
。我以前没遇到过 Embedded
。所以我会尝试这个作为我的 extension.plugin
:
[Plugin]
Name=My first libpeas extension
Module=extension.so
Loader=C