After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 164852 - non extern "C" callbacks
non extern "C" callbacks
Status: RESOLVED OBSOLETE
Product: glibmm
Classification: Bindings
Component: build
2.6.x
Other Linux
: Normal normal
: ---
Assigned To: gtkmm-forge
gtkmm-forge
Depends on:
Blocks:
 
 
Reported: 2005-01-21 19:37 UTC by Murray Cumming
Modified: 2018-05-22 12:05 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
externc.patch (27.55 KB, patch)
2005-01-21 20:05 UTC, Murray Cumming
none Details | Review
patch: Extern C without friend functions (1.99 KB, patch)
2017-06-14 14:10 UTC, Kjell Ahlstedt
none Details | Review

Description Murray Cumming 2005-01-21 19:37:14 UTC
glibmm has several callback functions that we give to glib, where they are
defined as extern "C" functions, but most of ours are not extern "C". The SUN
Forte compiler warns about this and the Tru64 compiler calls it an error when
using its "strict_ansi" option. This might get more important in future.

Unfortunately, most of these callbacks are static member functions, which can
not be extern "C". Changing them to separate functions means declaring them as
friend functions [1] to the class, and, because of the need to declare functions
before declaring them as friends, we often have to expose these functions as
public API, without the help of a private: or protected: keyword.

[1]: Though we could put these functions into an anonymous namespace, to prevent
them being exported as public API, we then have to way to refer to that
namespace in the "friend void some_function(int)" friend declaration.

The attached patch fixes some of this, as described, but it is not pretty.
Comment 1 Murray Cumming 2005-01-21 20:05:08 UTC
Created attachment 36347 [details] [review]
externc.patch

Fixes half of the extern "C" problems, often badly.
Comment 2 Tim Mooney 2005-02-03 23:13:52 UTC
I can confirm that I have run into this exact problem.

The error message from the compiler is similar to:

cxx: Error: iochannel.cc, line 112: a value of type
          "GIOStatus (*)(GIOChannel *, char *, gsize, gsize *, GError **)"
          cannot be used to initialize an entity of type
          "GIOStatus (*)(GIOChannel *, gchar *, gsize, gsize *, GError **) C"
  &GlibmmIOChannel::io_read,
--^

Comment 3 Murray Cumming 2005-02-04 07:28:07 UTC
Tim, what platform is that? With all compilers (g++, MSVC++, SUN, IRIX, Tru64,
AIX) that I've tried recently, the error can be avoided if you don't use some
compiler option. The SUN compiler always gives a warning.
Comment 4 Tim Mooney 2005-02-11 23:03:34 UTC
Sorry, I just noticed your question today.  I was confirming the problem on
Tru64 UNIX, with the `strict_ansi' option to the vendor cxx compiler.
Comment 5 Kjell Ahlstedt 2017-06-14 14:10:37 UTC
Created attachment 353742 [details] [review]
patch: Extern C without friend functions

This patch shows how to call a private static member function from a function
with "C" linkage without declaring the C function as a friend. All the ugly
code is added in the .cc file, nothing in the .h file.

The trick is to let the extern "C" function call the member function via a
function pointer, which is initialized from another member function.

If we really must separate extern "C" and extern "C++" functions, it would
required a _lot_ more fixes. We would also have to decide if it's acceptable
to use glib's function pointer types, like GClassInitFunc and GInstanceInitFunc,
in glibmm's public API. I've done so in Glib::ExtraClassInit's constructor,
for instance. The example code in ExtraClassInit's documentation wouldn't do.
It shows how to pass pointers to extern "C++" functions to the constructor.

Is this a real problem, a problem that we need to fix? I realize that it's a
potential problem, but it looks to me as if it was more of a problem 12 years
ago, when this bug report was filed, than it is now.
Comment 6 Daniel Boles 2017-08-13 15:17:39 UTC
It's a real problem in the sense that it relies on non-Standard behaviour that just happens to exist in extant compilers, but may not always. And given how much attention is given to writing correct and idiomatic C++ in so many other areas of the mm projects, it would be nice if this would follow suit.

Of course as you indicated, whether it's _practically_ a problem is a different question - albeit, again, I suspect an unknowably open one: being non-Standard means compilers' results could change at any time. I doubt they'll go out of their way to break things without a really good reason... but they _could_.
Comment 7 Daniel Boles 2017-08-13 15:20:02 UTC
I mean to include this link, which has some useful info: https://stackoverflow.com/questions/14395192/why-does-c11-not-support-declaring-extern-c-on-a-static-member-function plus another suggested way of working around this, which 'preserves' (emulates) the same call syntax.
Comment 8 Kjell Ahlstedt 2017-08-14 15:32:13 UTC
I don't understand how we can use the technique in the stackoverflow post that
you link to. The whole point of letting the callback function be a static member
function is that it shall be able to access private and protected data members
and methods in its class (e.g. Gtk::Application_Class) and in classes of which
it's a friend (e.g. Gtk::Application). In the final example in the stackoverflow
post, A::callback is a reference to a non-member function A_callback().
A_callback() can't access private and protected members of class A, unless it's
a friend of A. My contribution in comment 5 shows how we can avoid declaring
the callback functions as friends.

Clarification: Gtk::Xyz_Class is a friend of Gtk::Xyz. The default handler of
Gtk::Xyz::signal_abc() is Gtk::Xyz_Class::abc_callback().
Comment 9 GNOME Infrastructure Team 2018-05-22 12:05:54 UTC
-- GitLab Migration Automatic Message --

This bug has been migrated to GNOME's GitLab instance and has been closed from further activity.

You can subscribe and participate further through the new bug through this link to our GitLab instance: https://gitlab.gnome.org/GNOME/glibmm/issues/1.