Есть ли способ зарегистрировать типы из интроспекции gobject? - PullRequest
1 голос
/ 06 мая 2020

Я сейчас экспериментирую с библиотекой gobject-introspection. Одна вещь, которую я хотел бы сделать, - это иметь возможность регистрировать типы (в частности, классы) на основе информации, которую я могу получить. В частности, я могу получить GLib.Type, который затем могу использовать для создания экземпляра класса с GLib.Object.new

. Я успешно загрузил пространство имен из библиотеки типов, и я могу получить информацию о классах et c в пространстве имен, но я не уверен, как оттуда двигаться?

static void main(string[] args){

    var rep = GI.Repository.get_default();
    rep.require("Gtk", null, 0);

    var oinfo = (GI.ObjectInfo)rep.find_by_name("Gtk", "Button");

}

из oinfo теперь я могу легко получить имя, et c. класса, у меня там есть все метаданные, насколько я могу судить. Но предположим, что я не могу ссылаться на тип вроде: typeof(Gtk.Button) или иным образом напрямую ссылаться на него в коде, как мне зарегистрировать этот тип в системе типов, чтобы я мог создать его экземпляр?

1 Ответ

0 голосов
/ 16 мая 2020

Верно, поэтому я решил это сам, после МНОГО повозки. Но все оказалось не так уж и сложно. Наиболее сложный способ сделать это - использовать только что скомпилированную разделяемую библиотеку, поэтому мой пример будет включать следующее:

Сначала давайте создадим разделяемую библиотеку, содержащую только один класс в одном файле:

namespace TestLib{

    public class TestBase : Object{

        private static int counter = 0;

        public int count{
            get{
                return ++counter;
            }
        }

    }

}

Это должно быть скомпилировано в файл разделяемой библиотеки valac --library=TestLib -H TestLib-1.0.h --gir=TestLib-1.0.gir TestLib.vala -X -fPIC -X -shared -o TestLib.so Затем используйте компилятор gir и сгенерируйте typelib g-ir-compiler --shared-library=TestLib TestLib-1.0.gir -o TestLib-1.0.typelib

Затем мы пишем программу, которую хотим запустить:

using GI;

namespace TestRunner{

    static int main(string[] args){

        var namesp = "TestLib"; //set the name of the namespace we want to load
        var rep = Repository.get_default(); //Obtain default repository

        rep.require_private(".", namesp, null, 0); //load namespace info from the current folder (this assumes the typelib is here)

        var rtinfo = (RegisteredTypeInfo)rep.find_by_name(namesp, "TestBase"); //retrieves the BaseInfo of any type in the "TestLib" namespace called "TestBase" and casts it

        var type = rtinfo.get_g_type(); //Calls the get type, registrering the type with the type system, so now it can be used as we wish

        var objt = Object.new(type); //object is instantiated, and we can use it

        Value val = Value(typeof(int));
        objt.get_property("count", ref val);

        message(val.get_int().to_string());

        objt.get_property("count", ref val);

        message(val.get_int().to_string());

        message("type is: %s".printf(type.name()));

        return 0;

    }

}

Затем мы компилируем эту программу: valac TestLib.vapi TestRunner.vala -X TestLib.so -X -I. -o testintro --pkg=gobject-introspection-1.0 И перед тем, как запустить ее, мы не забудем добавить этот каталог в путь, чтобы программа знала, где найти общую библиотеку: export LD_LIBRARY_PATH=.

наконец запускаем новую программу: ./testintro

И мы должны увидеть:

** Message: 22:45:18.556: TestRunner.vala:9: Chosen namespace is: TestLib
** Message: 22:45:18.556: TestRunner.vala:24: 1
** Message: 22:45:18.556: TestRunner.vala:28: 2
** Message: 22:45:18.556: TestRunner.vala:30: type is: TestLibTestBase
...