Older blog entries for redi (starting at number 171)

10 Mar 2009 (updated 10 Mar 2009 at 14:07 UTC) »

I hope this will be a clearer explanation of my point ...

1. I want to create a shared library with the function my_callback. Because I want to support C programs, dlsym, and C++, I want my_callback to be unmangled; therefore, I put it in my_callback.h.
That conclusion doesn't follow from the requirements: putting it in my_callback.h is not sufficient. It would only be sufficient if the compiler magically switched language based on file extension, which isn't the case and the expectation of that behaviour is where your problem stems from.

The name is not mangled as a consequence of compiling it as C, not because you put it in a header or because the header has a particular name.

2. I compile my 100%-C library libmc.so.

3. program-a needs my_callback without hard-linking. Because my_callback isn't mangled, dlsym is an option.

dlsym is always an option, you just have to use the right symbol name. If it's a C++ function then the name will be mangled, which does make it tricker. In your case the symbol name isn't mangled, which admittedly makes things easier :-)

4. program-b needs my_callback with hard-linking. Because my_callback isn't mangled, program-b must either use extern "C" when including my_callback.h or my_callback.h needs to conditionally use extern "C" if C++ compilation is detected.
Right. See below.
This is because gcc infers that my_callback.h is meant to be a C++ header rather than at least implicitly giving it C linkage.
See my last diary entry.
The problem isn't apparent until link time, however; gcc mangles the name and an "undefined reference" error occurs.
Right. As it should.

The #include <my_callback.h> has exactly the same effect as pasting the contents of that header into the including file at that point. So if the header declares void my_callback(int); it is exactly as if you had written that directly into the including file. Obviously, had you done that, it would declare a function with extern "C++" linkage if you wrote it in a C++ file, and declare a function with extern "C" linkage if you wrote it in a C file. The fact the declaration was instead provided indirectly by including another file is irrelevant, and so is the name of that other file. If you want it to declare a function with extern "C" linkage in all cases then you are responsible for explicitly speciying the language linkage in the C++ case (and the obvious way to do that is with #ifdef __cplusplus etc.)

10 Mar 2009 (updated 10 Mar 2009 at 12:38 UTC) »
ta0kira, I understood you - but I think you misunderstand how the C and C++ preprocessors and separate compilation model works.

GCC does not "infer" that it's a C++ header file. By the time the compiler is processing the contents of the header it's not a separate file anymore, it's been combined with the main source file by the preprocessor (which happens before any compilation as either C or C++.)

The preprocessor simply includes the content of my_callback.h in the translation unit that says #include <my_callback.h>. If that translation unit is a C++ file being compiled by the C++ compiler, then the contents of my_callback.h are compiled (along with the rest of the translation unit) as C++. If it's a C file being compiled as C, then the contents of my_callback.h are compiled as C. That's it. There's no inference of anything at the granularity of individual headers. *

You are including a C header in a C++ translation unit. Despite their similarities, they are different languages. If you want the header to be valid as part of a C++ translation unit (declaring the functions with the desired linkage) then you need extern "C" to say that the functions use "C" linkage (meaning, among other things, the names are not mangled.) If you want the header to be valid in both C and C++ translation units (declaring the same functions with the desired linkage,) then you need to use #ifdef around the bits that are not valid C. That is your job, not the compiler's.

The compiler does not, and should not, "implicitly [give] it C++ linkage," any more than saying #include <foo.txt> should declare the contents of the text file as a const char[].

It is not just gcc and g++ that do this, it's how it's meant to work. You still seem to be blaming gcc for doing what it's meant to.

* GCC will sometimes infer the language to be used from the file extension, but only of files named on the command line. It will not infer a different language for separate files included by the preprocessor. See Invoking G++ for more details.

P.S. The reason that gcc and g++ behave the same is that they are both just drivers that invoke the compiler proper, the difference is that g++ automatically adds -lstdc++ and some related linker options when invoking the linker, and if no explicit -x option is given g++ assumes -x c++ (see the link above for a more accurate explanation.)

9 Mar 2009 (updated 9 Mar 2009 at 10:38 UTC) »
ta0kira, you're doing it wrong. Why should the compiler have to guess at the language of a header file, unless you're trying to compile that file directly (i.e. not via a #include in another file)? The included file is compiled in the same language as the including file. Therefore, it doesn't matter if I use .h as the extension or not, it only matters where I include it from.

You seem to be blaming gcc for doing what it's meant to.

6 Mar 2009 (updated 6 Mar 2009 at 10:14 UTC) »


Thanks, ncm, I'd forgotten about the libiberty joke. My US colleagues who rhyme "lib" with "gibe" are not from MS shops, so I wonder where they picked up the bad habit!

bagder comments on the pronunciation of "lib". In my experience only Americans say "libe" as though it's the start of "library", all Brits I know say "lib" to rhyme with "bib".

The C data type "char" (as either "char" or "car") doesn't seem to be so clearly divided by national boundaries.

In both cases I read it exactly as it's written, not as a shortened form of the word it originated from.

20 Feb 2009 (updated 20 Feb 2009 at 18:37 UTC) »

In a reply to one of his recent articles, lkcl said:

here's the secret, that you and everyone else who reads what i write, don't seem to be in on...

I take objection to "everyone else," lkcl was one of the first certs I gave on this site, and the only reason I removed the Master cert I'd given him was because of his certification of mentifex, not because I don't value his work. My feeble trust-juice will have no influence on either of their ratings, but that's not the point.

There's been some more brouhaha about KDE4 recently (well, recently when I first saved this draft diary entry) including Linus Torvalds announcing he's switched to gnome. Some commenters have said that people who aren't happy on the bleeding edge should not be using distros such as Fedora. I agree, but my problems with KDE4 are not that there are unstable, unreliable parts, which I expect from new releases. It's that basic functionality was removed, resulting in stupid regressions that still aren't fixed in KDE 4.2, despite claims that it is "a compelling offering for the majority of end users." The problems for Fedora users are exacerbated by the response to any KDE-related bug reported to Fedora bugzilla: "not our problem, report it upstream." (update: and in some cases claiming it's fixed without even bothering to check.)

Despite its flaws, I really do like my eee pc. Being able to hack on code while walking down the street is brillant.

Recently I did some hacking on std::thread for libstdc++, as I needed to make a small fix before I could finish std::bind and I got carried away making improvements to std::thread.

I also suggested a few patches for Boost to fix some problems in the (fscking excellent) new thread library. Unfortunately whether I report bugs to the boost list or to trac, they seem to fall between the cracks. The list has far too much traffic for me to follow, so I don't bother chasing them up.

I've realised that one of the things I like about smart pointers in C++ is what they tell you about the programmer. Smart programmers use smart pointers. The other group use raw, unsafe pointers.

chromatic confuses unit tests and TDD, but he's not alone in that.

I wonder why jcsteele also needs to syndicate his blog to selerius. I wonder why anyone needs to syndicate their twittering to advogato.

Spammer accounts seem to be on the rise again in the last few days. It's a testament to the incompetence and stupidity of most spammers and SEO twunts that they can't even enter the same thing in two fields e.g. creating an account as "ajax09" but putting the real name as "ajax 222" ... if they weren't such idiots it might be a lot harder to identify accounts created by spammers.

sucking shit

The Emperor's New Desktop

I still think KDE4 sucks enormous quantities of shit.

Xerces-C++ is a conspiracy to make C++ look bad

Xerces-C++ sucks even more shit. Writing a C++ API with unclear memory-ownership semantics was pretty dumb a decade ago. It just makes you look idiotic in 2009. Dynamic memory management in C++ is a solved problem. Requiring explicit calls to release memory at scope exit can be attributed to stupidity, but not providing an RAII type to restore some sanity to the API begins to look like malice.

diary of micro hacks

I had hoped to update GCC's std::tr1::bind and friends to also serve as std::bind (after breaking them and having to back out my changes a few weeks ago) but I didn't get any hacking done over twixtmas, except some small changes to the GCC manual and some largely pointless changes to the non-functional std::tr1::regex code.

Last week I updated the RPM spec files I wrote for STLsoft & Pantheios RPMs for Fedora. They're closer to the Fedora packaging guidelines now, and all my STLsoft patches have been accepted upstream which makes life simpler.

If I get time I might release some C++ container templates I wrote recently, worm::map<Key,T>, worm::set<T> and non-unique counterparts, which provide a similar interface to the standard associative containers but implemented using sorted std::vectors. This means they have random-access iterators and better memory locality, but sacrifice the nice iterator invalidation rules of the standard associative containers. I need to remove some sharp edges and figure out whether I can keep the same interface w.r.t const and ordering invariants, or whether I need to make them immutable to prevent self-inflicted gunshot wounds to the foot.

Movember - Sponsor Me I chickened out of Movember after only a week, as it was too itchy and with a cold I didn't fancy wiping snot from my 'tache all day! The badge to the left takes you to the sponsorship page of a friend who started it with me, but didn't give up.

162 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!