GithubHelp home page GithubHelp logo

pelagicore / gdbus-codegen-glibmm Goto Github PK

View Code? Open in Web Editor NEW
23.0 23.0 25.0 397 KB

Code generator for C++ D-Bus stubs and proxies using Giomm/Glibmm

License: GNU Lesser General Public License v2.1

Python 9.33% C++ 89.62% CMake 0.95% Shell 0.09%
code-generation dbus

gdbus-codegen-glibmm's People

Contributors

breakreturn avatar e8johan avatar erikboto avatar fhajredini avatar filug avatar jeremiah avatar jonte avatar kursatkobya avatar liebeym avatar mardy avatar martin-ejdestig avatar sashko avatar skumardas avatar tsansari avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

gdbus-codegen-glibmm's Issues

Empty *_set_finish() method for properties in proxy

Should they be removed? Left over from refactoring? Or are they there intentionally?

If intentional, I think a comment is in order in the body or something. It is confusing as it is now. (Do I need to call it to be future proof?)

Invalid results for parameterless signals with no return type

Starting out on my journey with DBus bindings so forgive me if I am doing something wrong/silly here...

Starting at the start: My goal is to generate a proxy object for Network Manager.

I can generate NetworkManager introspection XML with:
gdbus introspect --system --dest=org.freedesktop.NetworkManager --object-path=/org/freedesktop/NetworkManager --xml > generated/network_manager_introspect.xml

Then feed the XML into codegen:
gdbus-codegen-glibmm3 --generate-cpp-code=generated/network-manager generated/network_manager_introspect.xml --interface-prefix="org.freedesktop"

Firstly, this reproduces #77 as the sub-nodes are not populated in generated/network_manager_introspect.xml (stripping unnecessary detail):

...snip...

<node>
  <interface name="org.freedesktop.NetworkManager">

...snip...

  </interface>
  <node name="DnsManager"/>
  <node name="DHCP4Config"/>
  <node name="ActiveConnection"/>
  <node name="Devices"/>
  <node name="AgentManager"/>
  <node name="Settings"/>
  <node name="IP6Config"/>
  <node name="IP4Config"/>
</node>

Secondly, after deleting the sub-nodes, I tried feeding the modified XML into codegen again, it successfully generates the expected [cpp|h] files.
The 'CheckPermissions' signal: docs
that has no parameters and no return values is incorrectly generated in generated/network-manager_proxy.h:

class NetworkManager : public Glib::ObjectBase {
public:

...snip...

    sigc::signal<void,  > CheckPermissions_signal;

...snip...

Compile error for generated template function in proxy

First of all, thank you so much for providing this great utility. There seems to be trivial issue with the generated template function.

Input method schema:

        <method name="SetProperty">
            <arg name="name" type="s" direction="in"/>
            <arg name="value" type="v" direction="in"/>
        </method>

Generated proxy template function (indent as generated):

    template <typename T>
    void SetProperty(
        std::string name,
        T value,
        const Gio::SlotAsyncReady &callback)
    {
        Glib::VariantContainerBase base;
        std::vector<Glib::VariantBase> params;
        Glib::Variant<Glib::ustring> name_param = Glib::Variant<Glib::ustring>::create(arg_name);
        params.push_back(name_param);
        Glib::Variant<Glib::Variant<T> > value_variantValue;
        value_variantValue = Glib::Variant<Glib::Variant<T> >::create(Glib::Variant<T>::create(value_param));
        params.push_back(value_variantValue);
        base = Glib::VariantContainerBase::create_tuple(params);

    m_proxy->call(
        "SetProperty",
        callback,
        base);
}

Comparing the generated template function and other functions, it seems that the function argument naming and the variantValue reference are inconsistent. Is it correct that the template function should be generated as the following?

    template <typename T>
    void SetProperty(
        std::string arg_name,
        T arg_value,
        const Gio::SlotAsyncReady &callback)
    {
        ...
        Glib::Variant<Glib::ustring> name_param = Glib::Variant<Glib::ustring>::create(arg_name);
        ...
        value_variantValue = Glib::Variant<Glib::Variant<T> >::create(Glib::Variant<T>::create(arg_value));
        ...

Related code:

SyntaxError: Missing parentheses in call to 'print'

When running python setup.py install on master I'm getting a syntax error:

byte-compiling build/bdist.linux-x86_64/egg/codegen_glibmm/codegen.py to codegen.cpython-36.pyc
  File "build/bdist.linux-x86_64/egg/codegen_glibmm/codegen.py", line 227
    print "WARNING: signal %s has too many parameters, skipping" % s.name
                                                               ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(print "WARNING: signal %s has too many parameters, skipping" % s.name)?

byte-compiling build/bdist.linux-x86_64/egg/codegen_glibmm/parser.py to parser.cpython-36.pyc
byte-compiling build/bdist.linux-x86_64/egg/codegen_glibmm/codegen_main.py to codegen_main.cpython-36.pyc
byte-compiling build/bdist.linux-x86_64/egg/codegen_glibmm/dbustypes.py to dbustypes.cpython-36.pyc
  File "build/bdist.linux-x86_64/egg/codegen_glibmm/dbustypes.py", line 120
    print "Unknown signature: " + self.signature
                              ^
SyntaxError: Missing parentheses in call to 'print'. Did you mean print(print "Unknown signature: " + self.signature)?

Problem with signal sending.

Hi,
I was successfully generated stubs with methods and signals. I am trying to implement the dbus server using them. As it is quite easy to me to use stubs to implement the methods and call them, I have problem with signals implementation using stubs. I would like to evoke signal when by some external function to populate the string with message that something happened to another process.

Could you please give me any hint how to play with that?

This is part generated stub.cpp I am using:

<signal name="EventNotification">
    <arg name="EventString" type="s"/>
</signal>
void com::my::busname::Processor::EventNotification_emitter(std::string EventString) {
            std::vector<Glib::VariantBase> paramsList;

paramsList.push_back(Glib::Variant<Glib::ustring >::create((EventString)));;

m_connection->emit_signal(
              "/com/my/busname/Processor",
              "com.my.busname.Processor",
              "EventNotification",
              Glib::ustring(),
              Glib::Variant<std::vector<Glib::VariantBase> >::create_tuple(paramsList));
      }

I am trying to call : EventNotification_emmiter("Sample STRING");

This compile but after execution I have Segmentation fault (problem with memory).

EDIT:

void com::my::busname::Processor::EventNotification_emitter(std::string EventString) {
            std::vector<Glib::VariantBase> paramsList;

paramsList.push_back(Glib::Variant<Glib::ustring >::create((EventString)));;
std::cout << "tu jestem" << std::endl;

m_connection->emit_signal(
              "/com/my/busname/Processor",
              "com.my.busname.Processor",
              "EventNotification",
              Glib::ustring(),
              Glib::Variant<std::vector<Glib::VariantBase> >::create_tuple(paramsList));
      }

It seems that the debuger point those line as problematic:
Glib::Variant<std::vector<Glib::VariantBase> >::create_tuple(paramsList));

In Glib docs I am unable to find such a member function like create_tuple().

BR,

Krzysztof

Split common.h.templ into private and public headers and "seal" the private one

As e.g. GLib (and GTK does). Only <glib.h> is supposed to be included and all other headers are guarded by:

#if !defined (__GLIB_H_INSIDE__) && !defined (GLIB_COMPILATION)
#error "Only <glib.h> can be included directly."
#endif

commoh.h.templ currently contains *TypeWrap and Error if any error annotations are specified in introspection XML. *TypeWrap is not meant to be used externally (if I have understood things correctly) while Error is.

Could put *TypeWrap in common_private.h.templ and require FOO_BAR_OR_SOMETHING to be defined before it is included. Error would still stay in commoh.h.templ.

Only clang++ is worked.

When clang++ is converted to g++, compilation does not proceed. Can you tell me why?
The glib library is not referenced.

Complex signal arguments are passed by value and needlessly copied in both stub and proxy

Perhaps not that bad for a string, but e.g. have a signal that results in something like this in:

*_proxy.h:

    sigc::signal<void, Glib::DBusObjectPathString, std::map<Glib::ustring,Glib::VariantBase>> Foo_signal;

*_proxy.cpp:Proxy::handle_signal():

        if (parameters.get_n_children() != 2) return;
        Glib::Variant<Glib::DBusObjectPathString> base_arg1;
        parameters.get_child(base_arg1, 0);
        Glib::DBusObjectPathString p_arg1;
        p_arg1 = base_arg1.get();

        if (parameters.get_n_children() != 2) return;
        Glib::Variant<std::map<Glib::ustring,Glib::VariantBase>> base_arg2;
        parameters.get_child(base_arg2, 1);
        std::map<Glib::ustring,Glib::VariantBase> p_arg2;
        p_arg2 = base_properties.get();

        Foo_signal.emit((p_arg1), (p_arg2));

*_stub.cpp:

    void Foo_emitter(Glib::DBusObjectPathString, std::map<Glib::ustring,Glib::VariantBase>);
    sigc::signal<void, Glib::DBusObjectPathString, std::map<Glib::ustring,Glib::VariantBase>> Foo_signal;
void Stub::Foo_emitter(Glib::DBusObjectPathString arg1, std::map<Glib::ustring,Glib::VariantBase> arg2)
{
    std::vector<Glib::VariantBase> paramsList;

    paramsList.push_back(Glib::Variant<Glib::DBusObjectPathString>::create((arg1)));;
    paramsList.push_back(Glib::Variant<std::map<Glib::ustring,Glib::VariantBase>>::create((arg2)));;
    ...
}

Should perhaps add const & or && and std::move for non simple types where applicable.

Remove (or rework?) deprecated connect() method in stub

Not sure what the policy for backwards compatibility is, hence this issue instead of a pull request.

It is confusing to have it in the generated code.

Or perhaps maybe rework it? I guess the original intention was to hide the Gio::DBus::own_name() call from the user but the current implementation has some shortcomings (not possible to register multiple objects, nothing is done in name lost callback etc.) so register_object() was added in 92d9f83 .

But perhaps it makes sense to have some convenience API for Gio::DBus::own_name()? It just has to be more flexible?

Support file descriptor with Gio::UnixFDList

gdbus-codegen supports file descriptors as the following anntation and GUnixFDList.

<annotation name = "org.gtk.GDBus.C.UnixFD" value = "true" />

It would be nice if gdbus-codegen-glibmm also supports file descriptors with the same annotation and Gio::UnixFDList.

I'm using glibmm's low API because the generator doesn't support it right now, so the code is unnatural.

Namespace/class collision with interfaces where one is a prefix of another

If I try to include interfaces named like A.B and A.B.C at the same time, the B is defined as both a class and a namespace :(

panel/320e00e@@n9-panel@exe/org.freedesktop.UPower.Device_proxy.h:9:11: error: redefinition of 'UPower' as different kind of symbol
namespace UPower {
          ^
panel/320e00e@@n9-panel@exe/org.freedesktop.UPower_proxy.h:10:7: note: previous definition is here
class UPower : public Glib::ObjectBase {
      ^

For now I'm using --cpp-namespace as a workaround, but I wonder if a better solution is possible…

can't emit a signal without destination

The body of the {{signal.name}}_emitter in the stub.cpp.templ suggests that signals can't be simply broadcasted to be picked up by whoever client which has subscribed for signals via AddMatch.
The destinations for a signal should be known beforehand for emitter function to be able to emit targeted signals which IMHO is kind of in contrast with the message bus concept of signals.
I suggest to make the destination bus names optional and in case of empty list simply emit a signal without a destination.

Property names unnecessarily extracted when getting property values in proxy.

Gio::DBus::Proxy::get_cached_property() returns an empty (bool operator returns false) variant if property is not cached. That is, this:

{{ prop.cpptype_out }} {{ class_name_with_namespace }}::{{ prop.name }}_get()
{
    std::vector<Glib::ustring> props = m_proxy->get_cached_property_names();
    Glib::Variant<{{ prop.variant_type }}> b;
    if (std::find(props.begin(), props.end(), "{{ prop.name }}") != props.end()) {
        m_proxy->get_cached_property(b, "{{ prop.name }}");
    } else {
        g_print("Todo: lookup value\n");
    }

could be changed to something like:

{{ prop.cpptype_out }} {{ class_name_with_namespace }}::{{ prop.name }}_get()
{
    Glib::Variant<{{ prop.variant_type }}> b;
    m_proxy->get_cached_property(b, "{{ prop.name }}");
    if (!b) {
        g_print("Todo: lookup value\n");
    }

I think... :)

Provide an error domain in generated error classes

Due to the design of Glib::Error, the developer needs to have a way to retrieve the error domain associated with the generated error classes.
We should offer a static method which returns the GQuark.

Meanwhile, if RTTI is enabled, one can use dynamic_cast, with some pain.

Generate sync method/property set calls in proxy

Would simplify certain use cases (e.g. interactive command line tools) where D-Bus methods are called or properties are set but it is not important to be responsive while calls are pending.

If we do not want to generate sync versions all the time a command line option could be added to optionally turn it on.

Glib::RefPtr should probably not be passed by value

Glib::RefPtr and Glib::RefPtr wrapped helper classes should probably not be passed by value. A reference will be taken at call site, and in most cases object will just be dereferenced directly again when the call is done.

For instance, having the D-Bus method Test generates something similar to:

virtual void Test(FooMessageHelper msg) = 0;

in the stub. And FooMessageHelper has a RefPtr member variable.

A const & to the RefPtr (or simply a reference to the wrapped object) would probably be preferable.

*MessageHelper and *TypeWrap in commoh.h.templ not namespaced

Unsure why they are put in the global namespace.

Could namespace or perhaps better yet, nest TypeWrap in proxy and MessageHelper in stub.

Is it OK to change this? (Do not know what policy is with regards to backwards compatibility.) I can send a patch if it's OK and you tell me what you prefer.

I think nesting is better. I do not see why they are in common.h.templ. Not used in both proxy and stub. Am I missing something?

Limited number of signal arguments.

In fact, it is not a generator bug or limitation.

DBus signal is used by connecting xxx_emitter to sigc::signal, but sigc::signal can only use up to 7 arguments. So, if it exceeds the allowed number of arguments, it will not compile.

I think it may be helpful to output a warning message if there are too many arguments of the signal during code generation.

Race issue with reading properties on proxy object close after creation

Currently the <property name>_get() function only handles the case where the property is already in the local cache. The local cache population is started during the creation of the proxy (by calling GetAll asyncronously), but is not guaranteed to be finished before the proxy is complete. Therefore the users of the proxy might call a property's get() method when the value is not in the cache, which will just print a todo message.

This can be problematic since there's no way to tell if a proper value was read or not, at least not for e.g. a bool where the returned value will be false and there's no way of telling that the value is not reflecting the actual property value. You will however see some internal glib messages:

GLib-CRITICAL **: 09:11:41.658: g_variant_get_type: assertion 'value != NULL' failed
GLib-CRITICAL **: 09:11:41.658: g_variant_type_is_subtype_of: assertion 'g_variant_type_check (type)' failed
GLib-CRITICAL **: 09:11:41.658: g_variant_get_boolean: assertion 'g_variant_is_of_type (value, G_VARIANT_TYPE_BOOLEAN)' failed

I'm not really sure what the best approach here is:

  1. Pass an extra bool reference to the get function which could be used to indicate if the returned value is valid or not.
  2. Return the actual variant instead of variant.get(), but it would expose more of the internal glib structures to the user
  3. Add an async _get() method, so if the property cannot be read from cache it will be read using the org.freedesktop.DBus.Properties Get(). This might be a nice addition, but doesn't solve the problem with telling if the result from the synchronous _get() method is valid or not.

License of the generated code?

Hi, I saw this line at the bottom of the README:

"Source code licensed under the LGPL 2.1 (please see source code headers for more.)"

Is this applicable to the generated cpp source/header files? (Because there is no copyright notice in the generated files)
Would LGPL 2.1 mean I have to publish the generated sources?

I think it might be helpful to add a paragraph explaining licensing to the README.

Problem with methods that output (si)

Hi,

the problematic thing was to generate the method that get int as input argument, and output (si) - variant containing string and integer.
My solution:
In my code I overloaded the ret function in _common.h file to the following:

void ret(Glib::VariantContainerBase& p0)
{
m_message->return_value(p0);
}

then in my working class I implemented my example function as that:

virtual void myFunction (gint32 InArg, ProcessorMessageHelper msg)
  {
    std::cout << "HERE THE InArg IS: " << InArg << std::endl;

    Glib::VariantContainerBase::CType outArg = NULL;
    
    unsigned int outArg2 = InArg + 100;
    std::string outArg1 = "Example: " + std::to_string(InArg) + " VALUE IS: ";
    outArg = g_variant_new("(si)", outArg1.c_str(), outArg2);
    Glib::Variant<unsigned int> outVar(outArg);
    Glib::VariantContainerBase response = Glib::VariantContainerBase::create_tuple(outVar);

    msg.ret(response);
  }

I hope this can help someone to get the solution before the generator will be capable to solve that.

BTW: the example function is definied in XML as:

<method name="myFunction">
      <arg name="InArg"  direction="in"  type="i"/>
      <arg name="OutArg" direction="out" type="(si)"/>
</method>

BR
Krzysztof

Gio::DBus::InterfaceVTable memory leak in register_object() of stub

At least it looks like it to me:

guint {{ class_name_with_namespace }}::register_object(...)
{
    ...
    Gio::DBus::InterfaceVTable *interface_vtable =
        new Gio::DBus::InterfaceVTable(
            sigc::mem_fun(this, &{{ interface.cpp_class_name }}::on_method_call),
            sigc::mem_fun(this, &{{ interface.cpp_class_name }}::on_interface_get_property),
            sigc::mem_fun(this, &{{ interface.cpp_class_name }}::on_interface_set_property));
    guint id = 0;
    try {
        id = connection->register_object(object_path,
            introspection_data->lookup_interface("{{ interface.name }}"),
            *interface_vtable);    // NOTE: register_object() takes const InterfaceVTable &
        m_connection = connection;
        m_objectPath = object_path;
    } catch(const Glib::Error &ex) {
        g_warning("Registration of object failed");
    }
    // NOTE: interface_vtable leaked...
    return id;
}

The documentation says:

"The only correct use of this class is to declare a global instance of it (or an instance local to the main function) and pass pointers to the instance to the methods that require such a parameter. The instance can be used for multiple registrations and the memory it uses will be freed at the end of execution. Any other use (like creating an instance local to a function and using that) may cause memory leaks or errors (if the instance is destroyed too early)."

Bad for a long running service if objects are created and removed dynamically and each creation leaks.

Do not see a simple fix though since we cannot have a single instance and use sigc::mem_fun for the slots.

Make stub instances exportable over multiple object paths and connections

While not very common, there are cases where one might want to export the very same object over two different object paths. Also, especially when dealing with clients connecting directly to the service over a socket connection (bypassing the D-Bus daemon), it should be possible to export the same object over two different connections (on the same or on a different object path).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.