1

Almost all question here on SO ends up with answers for MSVC (def file or /EXPORT link option).

However there couple that mention gcc:

  1. How can i avoid name mangling? one mention using asm() in the source code. Since I'm not familiar with assembly I'm a little hesitant to use it.

  2. How do I stop name-mangling of my DLL's exported function? one mentions using -Wl,--kill-at option during the compilation/linking. However, I can't find anything like this in any gcc or link man pages online.

So, is there any way to avoid name mangling in C++ without using extern "C"?

Thank you.

[EDIT]

class Base
{
public:
    virtual void Foo() = 0;
};

class Derived : public Base
{
public:
    virtual void Foo() {};
};

extern "C" Base *MyExportedFunc()
{
    Base *pb = new Derived();
    return pb;
}

Without extern "C" MyExportedFunc() will have C++ linkage and the name will be mangled. And so I will not be able to simply call it from C++ code. With extern "C" the function is C-linkage. But then the function will not know about Base -> Derived relationship. And therefore the caller of the function will just see an address in the memory. It is a C function.

Hope it is clear now.

[/EDIT]

Community
  • 1
  • 1
Igor
  • 5,620
  • 11
  • 51
  • 103
  • 1
    You could put all your code into a single translation unit and give everything internal linkage, then you'll have no mangled names. – Kerrek SB Apr 16 '16 at 00:54
  • @KerrekSB, I'm trying to make my program modular. More over some pieces of depends on the external library1 and some on external library2. There is no reason to second part depend on library1 and vice versa. – Igor Apr 16 '16 at 01:01
  • Re option 1: The way gcc compiles c/c++ code is to convert it to an assembler output file, which it then passes on to an assembler which produces an object file, which is then passed to a linker to produce the executable. Using `asm("foo")` simply tells gcc what name to use for the function when creating the assembler output. Not a lot of assembler programming needed to understand that. The [docs](https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html) are pretty clear for this. – David Wohlferd Apr 16 '16 at 01:03
  • To whoever suggested the thread for solution - I did link it in my question, but I don't know anything about assembly, and therefore hesitant to use it as I don't want to screw things up. Besides there is a second solution which is also linked. – Igor Apr 16 '16 at 01:04
  • @DavidWohlferd, Can it be used cross-platform? Also what about solution number 2? – Igor Apr 16 '16 at 01:06
  • I take it you won't accept "no" as an answer? – Kerrek SB Apr 16 '16 at 01:17
  • I believe g++ supports .def module definition files. But I haven't checked. Anyway `extern "C"` is a part of any practical solution, so why don't you want it? – Cheers and hth. - Alf Apr 16 '16 at 01:17
  • Are you trying to do exports in a dll? I didn't get that from your question. Maybe the [visible](https://gcc.gnu.org/wiki/Visibility) attribute? – David Wohlferd Apr 16 '16 at 01:19
  • @DavidWohlferd, yes I'm trying to export from dll/so/dylib. About "attribute": which one? This is also code modification, right? – Igor Apr 16 '16 at 01:31
  • The "visible" attribute. I provided a link? – David Wohlferd Apr 16 '16 at 02:12
  • @DavidWohlferd, I looked at the link. The code in section "How to use the new C++ visibility support" still uses extern "C". This is what I'd like to avoid. – Igor Apr 16 '16 at 02:29
  • @Igor: **WHY** don't you want `extern "C"`. – Cheers and hth. - Alf Apr 16 '16 at 02:49
  • @Cheersandhth.-Alf, Because the function should return C++ class pointer and C-linkage function does not know anything about C++ classes, inheritance and polymorphysm. – Igor Apr 16 '16 at 04:35
  • @Igor: Linking and calling is no problem. This is unrelated to name mangling or lack thereof. However, if the class is non-POD it gets nasty fast (even with full C++ linkage, because the DLL code may not necessarily use the same memory allocator etc. as the main program). – Cheers and hth. - Alf Apr 16 '16 at 04:39
  • @Cheersandhth.-Alf, please see the edit to the question. Hopefully now it is more clear. – Igor Apr 16 '16 at 04:48
  • 2
    @Igor: It's more clear. It's a non-problem. “I will not be able to simply call it from C++ code” is incorrect. – Cheers and hth. - Alf Apr 16 '16 at 04:49
  • @Cheersandhth.-Alf, What do you mean? Could you please explain? Could you put some code? Both dlopen()/dlsym() and LoadLibrary()/GetProcAddress() won't be able to find it... Without extern "C" that is. – Igor Apr 16 '16 at 04:51
  • The code you posted is OK. It's non-problematic as C++ code. The main problem is, as mentioned, that the DLL may use a different memory allocator than the main program. One way to avoid that problem is to make sure that both link with a DLL version of the runtime library. – Cheers and hth. - Alf Apr 16 '16 at 04:54
  • Btw., a tip: in class `Derived`, better use the keyword `override` to mark this as an override. The keyword `virtual` is superfluous here. – Cheers and hth. - Alf Apr 16 '16 at 04:55
  • @Cheersandhth.-Alf, ok, so with MSVC I am linking to CRT dynamically and with extern "C" I am receiving back just the pointer to the memory - no class information. But everything is good without extern "C" and with /EXPORT:MyExportedFunc. – Igor Apr 16 '16 at 04:58
  • The "no class information" claim is wrong, unless you change the return type. You can just try this out. – Cheers and hth. - Alf Apr 16 '16 at 05:03
  • @Cheersandhth.-Alf, I can clearly see with the debugger that the pointer does not have any inheritance information. It just an address in the memory. That's why I want the C++ unmangling name that will return the C++ class pointer and not just "void *" as in C. MSVC allows it with def file, why not gcc linker? – Igor Apr 16 '16 at 05:08
  • "I can clearly see with the debugger that the pointer does not have any inheritance information.". If you call the function *from the debugger* you won't be able to see the type information, because *the debugger* cannot see declarations and may only obtain type information from the mangled name. Your program sees declarations, so calling your function *from a C++ program* is not a problem. – n. m. could be an AI Apr 16 '16 at 07:01
  • The usual practice for interface boundaries is to have a C API that deals in void pointers, and all the class-specific code lives purely on the C++ side. Then the API is easy to specify and implement, and it has the bonus of separating all the C++ code from the users so that you can maintain it freely. – Kerrek SB Apr 16 '16 at 10:18
  • @KerrekSB This is one practice, which is very far from being universal. – n. m. could be an AI Apr 16 '16 at 10:29

1 Answers1

4

is there any way to avoid name mangling in C++ without using extern "C"?

No. You might be able to do this for certain functions with certain compilers in a non-portable way. This is never needed in normal C++ development.

Without extern "C" MyExportedFunc() will have C++ linkage and the name will be mangled. And so I will not be able to simply call it from C++ code.

This is incorrect. You may not be able to easily find it with functions like dlsym, which hardly qualifies as simply calling it from C++ code. Normal linking and calling is not a problem.

With extern "C" the function is C-linkage. But then the function will not know about Base -> Derived relationship.

This is also incorrect. extern "C" does not preclude a function from using any C++ features.

To conclude: the common practice of creating normal (linked-against) C++ libraries is to not take name mangling into consideration. The common practice of creating plugins (loadable libraries used with dlsym/GetProcedureAddress) is to use extern "C".

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243
  • Well, for a DLL, which is the OP's use case, you can just a .def module definition file to define the names of the DLL's exports. Not sure exactly how one would import these in C++ without `extern "C"`, though. It's a totally impractical approach so I haven't ever done that. – Cheers and hth. - Alf Apr 16 '16 at 06:33
  • @Cheersandhth.-Alf sorry, got distracted and posted an unfinished answer. It's all ready now. – n. m. could be an AI Apr 16 '16 at 09:08
  • @n.m., The trouble is that with extern "C" all I get outside is just a memory address. I can clearly see it under the MSVC debugger. I just click a '+' sign next to the pointer and there is no reference of Derived class. It behaves as if it forgets what this pointer is. When I use /EXPORT:MyExportedFunc I do see such a reference, but then I need such a solution for gcc/Linux. – Igor Apr 16 '16 at 13:07
  • @Igor This is a non-issue.I have addressed it in another comment under your question. – n. m. could be an AI Apr 16 '16 at 14:52
  • @Igor instead of trying to overcome imaginary difficulties, take an existing C++ library and learn how it works. There are quite a few that exist out there. You are not the first person that tries to write one. – n. m. could be an AI Apr 16 '16 at 14:54
  • @Igor If you want some anecdotal evidence, here it is.I write and maintain cross platform (Windows and Linux) loadable C++ plugins for a living. I export C++ functions returning pointers to C++ objects with `extern "C"`. Do what you want with this information. – n. m. could be an AI Apr 16 '16 at 15:02
  • @n.m., Weird what compilers do you use? Is it C++11 code? – Igor Apr 16 '16 at 16:34
  • I'm building with MSVC 2010 under Win 8.1. I'm upgrading my Linux box right now and will test there as soon as it finishes upgrading. – Igor Apr 16 '16 at 16:35
  • MSVC 2010 under various Windows systems, gcc under various Linux systems. C++11, C++03, whatever. It works the way it is designed and supposed to work. I don't understand why you insist on the contrary. I don't quite understand what your problem is. Do you have a program that doesn't work the way you want it to work? Post a [mcve]. – n. m. could be an AI Apr 16 '16 at 16:46
  • @n.m. Here is the problem - I tried 3 different ways: plain console app, MFC app and wxWidgets app. While first 2 works fine, wxWidgets-based one does not. I have all 3 of them very basic test ones on my machine. I can upload them anywhere you want for analyzing. .And unfortunatelyI'm using wxWidgets for my development. The code along with the projects are very basic and use the same dll's and executable structure. – Igor Apr 16 '16 at 17:06
  • So you have a console app working, MFC app working, and wxWidgets app not working, and for some inexplicable reason you ask about name mangling. Did name mangling prevent your console app or MFC app from working? I have no idea about wxWidgets. You may have better luck if you ask a different question, tag it with the wxWidgets tag, and provide as much relevant information as possible. This question was not particularly productive. – n. m. could be an AI Apr 16 '16 at 17:26