get/set wrap methods.

classic Classic list List threaded Threaded
23 messages Options
12
Reply | Threaded
Open this post in threaded view
|

get/set wrap methods.

Pavlo Solntsev-2
I am trying to wrap a simple structure from libgda package. I followed some examples and documentation and was able to implement all get/set methods via _MEMBER_GET macros. The generated code looks exactly as I would expect for c++ get/set:

const T& get_some()const;
void set_some(const T&);

My question about getter. It looks like I return a reference for the temporary created object, which is not good. Do you think getter should return Glib::RefPtr<>? It is a little uncommon for c++ in my opinion. Does it cause any performance degradation by creating a RefPtr object and returning it? 

As an example, we may consider a simple struct:
struct Person {
char *fname;
char *lname;
};

Thanks,

-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Kjell Ahlstedt-2

What does your _MEMBER_GET() macros look like? You specify the type of the returned C++ value as the 3rd argument to _MEMBER_GET(), and if it's not the same as the C type of the structure member, you add a _CONVERSION() macro.

Kjell

Den 2018-02-22 kl. 17:05, skrev Pavlo Solntsev:
I am trying to wrap a simple structure from libgda package. I followed some examples and documentation and was able to implement all get/set methods via _MEMBER_GET macros. The generated code looks exactly as I would expect for c++ get/set:

const T& get_some()const;
void set_some(const T&);

My question about getter. It looks like I return a reference for the temporary created object, which is not good. Do you think getter should return Glib::RefPtr<>? It is a little uncommon for c++ in my opinion. Does it cause any performance degradation by creating a RefPtr object and returning it? 

As an example, we may consider a simple struct:
struct Person {
char *fname;
char *lname;
};

Thanks,

-Pavlo Solntsev



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Daniel Boles
also, I don't see how RefPtr is relevant to the given example struct; it's only for Glib::Object instances, i.e. things that themselves wrap GObjects, as RefPtr is implemented via GObject refcounts.

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Daniel Boles
On 22 February 2018 at 18:32, Daniel Boles <[hidden email]> wrote:
also, I don't see how RefPtr is relevant to the given example struct; it's only for Glib::Object instances, i.e. things that themselves wrap GObjects, as RefPtr is implemented via GObject refcounts.

...in the currently stable glibmm, at least. Beyond that, in the next release, it'll be an std::shared_ptr, layering a different layer of refcounting over GObject's own.

but the point stands: what would a RefPtr to a char* or any other simple property type even mean? They should just be returned by value, not by reference.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Pavlo Solntsev-2
Thanks for comments.  My macroses:

  _MEMBER_GET(name,name,const Glib::ustring&,const gchar*)
  _MEMBER_SET(name,name,Glib::ustring,gchar*)

the generated code :
const Glib::ustring& DsnInfo::get_name() const
{
  return Glib::convert_const_gchar_ptr_to_ustring(gobj()->name); // This is my concern. it looks like we return ref for temp object
}

void DsnInfo::set_name(const Glib::ustring& value)
{
  gobj()->name = g_strdup((value).c_str());
}

Thanks.

-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Thu, Feb 22, 2018 at 12:34 PM, Daniel Boles <[hidden email]> wrote:
On 22 February 2018 at 18:32, Daniel Boles <[hidden email]> wrote:
also, I don't see how RefPtr is relevant to the given example struct; it's only for Glib::Object instances, i.e. things that themselves wrap GObjects, as RefPtr is implemented via GObject refcounts.

...in the currently stable glibmm, at least. Beyond that, in the next release, it'll be an std::shared_ptr, layering a different layer of refcounting over GObject's own.

but the point stands: what would a RefPtr to a char* or any other simple property type even mean? They should just be returned by value, not by reference.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Daniel Boles
On 22 February 2018 at 19:56, Pavlo Solntsev <[hidden email]> wrote:
Thanks for comments.  My macroses:

  _MEMBER_GET(name,name,const Glib::ustring&,const gchar*)
  _MEMBER_SET(name,name,Glib::ustring,gchar*)

the generated code :
const Glib::ustring& DsnInfo::get_name() const
{
  return Glib::convert_const_gchar_ptr_to_ustring(gobj()->name); // This is my concern. it looks like we return ref for temp object
}


Of course it returns that. You just told it to! Look at the 2nd parameter of your _MEMBER_GET() declaration.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Kjell Ahlstedt-2
In reply to this post by Pavlo Solntsev-2

Your concern is justified. The Glib::ustring must be returned by value. The _MEMBER_GET should be

  _MEMBER_GET(name, name, Glib::ustring, const gchar*)

Your _MEMBER_SET macro doesn't seem to fit the generated code that you show. I would think that
  _MEMBER_SET(name, name, const Glib::ustring&, gchar*)
would generate that code. In this case a reference is OK, but it looks like the generated code can cause a memory leak. Who owns the duplicated string? Who deallocates it? What if gobj()->name contains a pointer to a string when set_name() is called?

Kjell

Den 2018-02-22 kl. 20:56, skrev Pavlo Solntsev:
Thanks for comments.  My macroses:

  _MEMBER_GET(name,name,const Glib::ustring&,const gchar*)
  _MEMBER_SET(name,name,Glib::ustring,gchar*)

the generated code :
const Glib::ustring& DsnInfo::get_name() const
{
  return Glib::convert_const_gchar_ptr_to_ustring(gobj()->name); // This is my concern. it looks like we return ref for temp object
}

void DsnInfo::set_name(const Glib::ustring& value)
{
  gobj()->name = g_strdup((value).c_str());
}

Thanks.

-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Thu, Feb 22, 2018 at 12:34 PM, Daniel Boles <[hidden email]> wrote:
On 22 February 2018 at 18:32, Daniel Boles <[hidden email]> wrote:
also, I don't see how RefPtr is relevant to the given example struct; it's only for Glib::Object instances, i.e. things that themselves wrap GObjects, as RefPtr is implemented via GObject refcounts.

...in the currently stable glibmm, at least. Beyond that, in the next release, it'll be an std::shared_ptr, layering a different layer of refcounting over GObject's own.

but the point stands: what would a RefPtr to a char* or any other simple property type even mean? They should just be returned by value, not by reference.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list




_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Pavlo Solntsev-2
In reply to this post by Daniel Boles
Yes, I did. because my goal is to get 
const T& get_name()const 
method. I need to return a reference. 


-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Fri, Feb 23, 2018 at 3:40 AM, Daniel Boles <[hidden email]> wrote:
On 22 February 2018 at 19:56, Pavlo Solntsev <[hidden email]> wrote:
Thanks for comments.  My macroses:

  _MEMBER_GET(name,name,const Glib::ustring&,const gchar*)
  _MEMBER_SET(name,name,Glib::ustring,gchar*)

the generated code :
const Glib::ustring& DsnInfo::get_name() const
{
  return Glib::convert_const_gchar_ptr_to_ustring(gobj()->name); // This is my concern. it looks like we return ref for temp object
}


Of course it returns that. You just told it to! Look at the 2nd parameter of your _MEMBER_GET() declaration.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Daniel Boles
You might think you need that, but you can't do it, because there is nothing permanent to reference, only a temporary created by the conversion to ustring.

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Pavlo Solntsev-2
In reply to this post by Kjell Ahlstedt-2
>>>  Your concern is justified. The Glib::ustring must be returned by value. The _MEMBER_GET should be
It is interesting. getter must return by value....

>>> Your _MEMBER_SET macro doesn't seem to fit the generated code that you show. I would think that
>>>  _MEMBER_SET(name, name, const Glib::ustring&, gchar*)

My understanding that the generated type will be const T& if T is provided to the macros. 

dnl Creates accessors for simple types:
define(`_MEMBER_SET',`dnl
ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_START ')dnl
void set_$1(const $3`'& value);
ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_END ')dnl
_PUSH(SECTION_CC)
ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_START ')dnl
void __CPPNAME__::set_$1(const $3`'& value)
{
gobj()->$2 = _CONVERT($3,$4,`value');
}
ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_END ')dnl
_POP()')



>> would generate that code. In this case a reference is OK, but it looks like the generated code can cause a memory leak. Who owns the duplicated string? Who deallocates it? What if gobj()->name contains a pointer to a string when set_name() is called?


Basically once again, return by value. What would be the correct wrap for the simple struct? Wrap struct and manually wrap set/get method?

I will investigate how private members are stored and how they related to the original C struct. Thanks



-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Fri, Feb 23, 2018 at 4:02 AM, Kjell Ahlstedt <[hidden email]> wrote:

Your concern is justified. The Glib::ustring must be returned by value. The _MEMBER_GET should be

  _MEMBER_GET(name, name, Glib::ustring, const gchar*)

Your _MEMBER_SET macro doesn't seem to fit the generated code that you show. I would think that
  _MEMBER_SET(name, name, const Glib::ustring&, gchar*)
would generate that code. In this case a reference is OK, but it looks like the generated code can cause a memory leak. Who owns the duplicated string? Who deallocates it? What if gobj()->name contains a pointer to a string when set_name() is called?

Kjell


Den 2018-02-22 kl. 20:56, skrev Pavlo Solntsev:
Thanks for comments.  My macroses:

  _MEMBER_GET(name,name,const Glib::ustring&,const gchar*)
  _MEMBER_SET(name,name,Glib::ustring,gchar*)

the generated code :
const Glib::ustring& DsnInfo::get_name() const
{
  return Glib::convert_const_gchar_ptr_to_ustring(gobj()->name); // This is my concern. it looks like we return ref for temp object
}

void DsnInfo::set_name(const Glib::ustring& value)
{
  gobj()->name = g_strdup((value).c_str());
}

Thanks.

-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Thu, Feb 22, 2018 at 12:34 PM, Daniel Boles <[hidden email]> wrote:
On 22 February 2018 at 18:32, Daniel Boles <[hidden email]> wrote:
also, I don't see how RefPtr is relevant to the given example struct; it's only for Glib::Object instances, i.e. things that themselves wrap GObjects, as RefPtr is implemented via GObject refcounts.

...in the currently stable glibmm, at least. Beyond that, in the next release, it'll be an std::shared_ptr, layering a different layer of refcounting over GObject's own.

but the point stands: what would a RefPtr to a char* or any other simple property type even mean? They should just be returned by value, not by reference.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list




_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Jonathan Wakely
In reply to this post by Pavlo Solntsev-2
On 23 February 2018 at 14:22, Pavlo Solntsev wrote:
Yes, I did. because my goal is to get 
const T& get_name()const 
method. I need to return a reference. 


Then you need to change your type to have a using member.

You can't have it both ways (return a reference, but not have something to bind the reference to).

Pick one. 

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Pavlo Solntsev-2
In reply to this post by Daniel Boles
Daniel, 
now it is clear. Basically, this is glibmm limitation for now. 

-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Fri, Feb 23, 2018 at 8:25 AM, Daniel Boles <[hidden email]> wrote:
You might think you need that, but you can't do it, because there is nothing permanent to reference, only a temporary created by the conversion to ustring.

_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Jonathan Wakely
In reply to this post by Jonathan Wakely
On 23 February 2018 at 14:37, Jonathan Wakely wrote:
On 23 February 2018 at 14:22, Pavlo Solntsev wrote:
Yes, I did. because my goal is to get 
const T& get_name()const 
method. I need to return a reference. 


Then you need to change your type to have a using member.

Sorry, for the typo, that was meant to say "ustring member"

 

You can't have it both ways (return a reference, but not have something to bind the reference to).

Pick one. 


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Daniel Boles
In reply to this post by Pavlo Solntsev-2
> Basically, this is glibmm limitation for now. 

I can see no way that this is any fault or limitation of glibmm's. It is rather a simple fact of any language supporting reference semantics: You can't (safely, usefully) have a reference of a given type unless you have an instance of that type, with at least the same lifetime as that of the reference.

You have a char* but want to return a Glib::ustring&; these are not compatible facts. So, the Glib::ustring must be created whenever requested, and returned by value. If you want to return a Glib::ustring&, keep a Glib::ustring somewhere, and use a reference to that.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Daniel Boles
I guess we should point out that a const& reference can extend the lifetime of temporaries in a different situation, namely where it binds to a local temporary, but that is not applicable when the referent is a class member or anything else except a local temporary.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Pavlo Solntsev-2
In reply to this post by Daniel Boles
Daniel, 

now it is clear. I didn't and still don't understand exactly how internal data members are represented in the generated class (I have no access to my code now) but the situation I have by returning a reference is clear. BTW does it make sense to think about shared_ptr as returned value for getter? 

-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Fri, Feb 23, 2018 at 8:42 AM, Daniel Boles <[hidden email]> wrote:
> Basically, this is glibmm limitation for now. 

I can see no way that this is any fault or limitation of glibmm's. It is rather a simple fact of any language supporting reference semantics: You can't (safely, usefully) have a reference of a given type unless you have an instance of that type, with at least the same lifetime as that of the reference.

You have a char* but want to return a Glib::ustring&; these are not compatible facts. So, the Glib::ustring must be created whenever requested, and returned by value. If you want to return a Glib::ustring&, keep a Glib::ustring somewhere, and use a reference to that.


_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Jonathan Wakely
On 23 February 2018 at 14:55, Pavlo Solntsev wrote:
Daniel, 

now it is clear. I didn't and still don't understand exactly how internal data members are represented in the generated class (I have no access to my code now) but the situation I have by returning a reference is clear. BTW does it make sense to think about shared_ptr as returned value for getter? 


No, because unless you keep a copy of the shared_ptr as a member, you will get a new shared_ptr each time you call it, which doesn't share ownership with the previous ones.

So now you have the shared_ptr overhead (reference counting) and inconvenience (needing to use operator* to access the value), without any sharing.

You might as well just return by value, or have a Glib::ustring member.



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Kjell Ahlstedt-2
In reply to this post by Pavlo Solntsev-2
Den 2018-02-23 kl. 15:36, skrev Pavlo Solntsev:
>>>  Your concern is justified. The Glib::ustring must be returned by value. The _MEMBER_GET should be
It is interesting. getter must return by value....

>>> Your _MEMBER_SET macro doesn't seem to fit the generated code that you show. I would think that
>>>  _MEMBER_SET(name, name, const Glib::ustring&, gchar*)

My understanding that the generated type will be const T& if T is provided to the macros. 

dnl Creates accessors for simple types:

define(`_MEMBER_SET',`dnl

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_START ')dnl

void set_$1(const $3`'& value);

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_END ')dnl

_PUSH(SECTION_CC)

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_START ')dnl

void __CPPNAME__::set_$1(const $3`'& value)

{

gobj()->$2 = _CONVERT($3,$4,`value');

}

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_END ')dnl


_POP()')




Sorry, I was wrong. _MEMBER_SET(name, name, Glib::ustring, gchar*)
does generate the code you showed.
>> would generate that code. In this case a reference is OK, but it looks like the generated code can cause a memory leak. Who owns the duplicated string? Who deallocates it? What if gobj()->name contains a pointer to a string when set_name() is called?


Basically once again, return by value. What would be the correct wrap for the simple struct? Wrap struct and manually wrap set/get method?

I will investigate how private members are stored and how they related to the original C struct. Thanks

In Glib::OptionEntry, _MEMBER_SET is not used for strings. Those methods are hand-coded to avoid a memory leak. Example:
void OptionEntry::set_long_name(const Glib::ustring& value)
{
  if (gobject_->long_name)
  {
    g_free((gchar*)(gobject_->long_name));
    gobject_->long_name = nullptr;
  }

  gobj()->long_name = (value).c_str() ? g_strdup((value).c_str()) : nullptr;
}

Don't ask me why value.c_str() is tested for nullptr. I don't understand. I don't think it can ever be a nullptr. And even if it is, g_strdup() can handle that.


-Pavlo Solntsev



_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Pavlo Solntsev-2
Perfect! Now I understand the methodology to implement setter for a structure. Do you think it would make sense to have a macro for this?  Say, _MEMBER_SET_CHAR. 

-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Fri, Feb 23, 2018 at 9:43 AM, Kjell Ahlstedt <[hidden email]> wrote:
Den 2018-02-23 kl. 15:36, skrev Pavlo Solntsev:
>>>  Your concern is justified. The Glib::ustring must be returned by value. The _MEMBER_GET should be
It is interesting. getter must return by value....

>>> Your _MEMBER_SET macro doesn't seem to fit the generated code that you show. I would think that
>>>  _MEMBER_SET(name, name, const Glib::ustring&, gchar*)

My understanding that the generated type will be const T& if T is provided to the macros. 

dnl Creates accessors for simple types:

define(`_MEMBER_SET',`dnl

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_START ')dnl

void set_$1(const $3`'& value);

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_END ')dnl

_PUSH(SECTION_CC)

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_START ')dnl

void __CPPNAME__::set_$1(const $3`'& value)

{

gobj()->$2 = _CONVERT($3,$4,`value');

}

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_END ')dnl


_POP()')




Sorry, I was wrong. _MEMBER_SET(name, name, Glib::ustring, gchar*)
does generate the code you showed.
>> would generate that code. In this case a reference is OK, but it looks like the generated code can cause a memory leak. Who owns the duplicated string? Who deallocates it? What if gobj()->name contains a pointer to a string when set_name() is called?


Basically once again, return by value. What would be the correct wrap for the simple struct? Wrap struct and manually wrap set/get method?

I will investigate how private members are stored and how they related to the original C struct. Thanks

In Glib::OptionEntry, _MEMBER_SET is not used for strings. Those methods are hand-coded to avoid a memory leak. Example:
void OptionEntry::set_long_name(const Glib::ustring& value)
{
  if (gobject_->long_name)
  {
    g_free((gchar*)(gobject_->long_name));
    gobject_->long_name = nullptr;
  }

  gobj()->long_name = (value).c_str() ? g_strdup((value).c_str()) : nullptr;
}

Don't ask me why value.c_str() is tested for nullptr. I don't understand. I don't think it can ever be a nullptr. And even if it is, g_strdup() can handle that.


-Pavlo Solntsev




_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
Reply | Threaded
Open this post in threaded view
|

Re: get/set wrap methods.

Pavlo Solntsev-2
Just submitted a patch for a macro to generate setter for char* member in consistent way. Please review.
https://bugzilla.gnome.org/show_bug.cgi?id=793778


-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Fri, Feb 23, 2018 at 10:12 AM, Pavlo Solntsev <[hidden email]> wrote:
Perfect! Now I understand the methodology to implement setter for a structure. Do you think it would make sense to have a macro for this?  Say, _MEMBER_SET_CHAR. 

-Pavlo Solntsev
---------------------------------------------------------------------------------------------
Please avoid sending me Word or PowerPoint attachments.
See http://www.gnu.org/philosophy/no-word-attachments.html


On Fri, Feb 23, 2018 at 9:43 AM, Kjell Ahlstedt <[hidden email]> wrote:
Den 2018-02-23 kl. 15:36, skrev Pavlo Solntsev:
>>>  Your concern is justified. The Glib::ustring must be returned by value. The _MEMBER_GET should be
It is interesting. getter must return by value....

>>> Your _MEMBER_SET macro doesn't seem to fit the generated code that you show. I would think that
>>>  _MEMBER_SET(name, name, const Glib::ustring&, gchar*)

My understanding that the generated type will be const T& if T is provided to the macros. 

dnl Creates accessors for simple types:

define(`_MEMBER_SET',`dnl

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_START ')dnl

void set_$1(const $3`'& value);

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_END ')dnl

_PUSH(SECTION_CC)

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_START ')dnl

void __CPPNAME__::set_$1(const $3`'& value)

{

gobj()->$2 = _CONVERT($3,$4,`value');

}

ifelse(`$5',`deprecated',`_DEPRECATE_IFDEF_END ')dnl


_POP()')




Sorry, I was wrong. _MEMBER_SET(name, name, Glib::ustring, gchar*)
does generate the code you showed.
>> would generate that code. In this case a reference is OK, but it looks like the generated code can cause a memory leak. Who owns the duplicated string? Who deallocates it? What if gobj()->name contains a pointer to a string when set_name() is called?


Basically once again, return by value. What would be the correct wrap for the simple struct? Wrap struct and manually wrap set/get method?

I will investigate how private members are stored and how they related to the original C struct. Thanks

In Glib::OptionEntry, _MEMBER_SET is not used for strings. Those methods are hand-coded to avoid a memory leak. Example:
void OptionEntry::set_long_name(const Glib::ustring& value)
{
  if (gobject_->long_name)
  {
    g_free((gchar*)(gobject_->long_name));
    gobject_->long_name = nullptr;
  }

  gobj()->long_name = (value).c_str() ? g_strdup((value).c_str()) : nullptr;
}

Don't ask me why value.c_str() is tested for nullptr. I don't understand. I don't think it can ever be a nullptr. And even if it is, g_strdup() can handle that.


-Pavlo Solntsev





_______________________________________________
gtkmm-list mailing list
[hidden email]
https://mail.gnome.org/mailman/listinfo/gtkmm-list
12