Author Topic: GCC/G++ - how to export global variable without underscore?  (Read 5501 times)

Andi B.

  • Hero Member
  • *****
  • Posts: 870
  • Karma: +14/-2
    • View Profile
I'm trying to build a dll which should export some functions and global variables. I made this long time ago I think with our gcc3.xx but now want to do the same with our g++.exe (GCC) 9.2.0.

I think exporting symbols is disabled now by default so I added to the functions I want to export
Code: [Select]
__attribute__ ((dllexport)) which works fine. Now when I look at my dll with
Code: [Select]
lxlite /C:exp myown.dllI see the exported functions as I expected.

But my global variables still have the C naming convention leading _ which I don't like. F.i. I have -
Code: [Select]
00048 │ _NdpAttribute
00049 │ _NdpPropertiesInfo
00050 ┴ _NdpTypes
but I wanna have them without the _

The variables are defined that way -
Code: [Select]
__attribute__ ((dllexport)) extern const char *NdpTypes[];and I use g++ instead gcc. So I thought it should work the same as with the functions (they don't have the _).

Any thoughts?


Dave Yeo

  • Hero Member
  • *****
  • Posts: 5083
  • Karma: +117/-1
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #1 on: June 30, 2024, 11:13:08 pm »
It's the calling convention, cdecl vs stdcall. I think you need __attribute__ ((__cdecl)), might be ((__stdlib)) and __declspec instead of __attribute__
Code: [Select]
__attribute__ ((dllexport)) __attribute__((__stdcall)) extern const char *NdpTypes[];
or __cdecl
Been a while since I thought about this so sorry for being unclear, needed it in the past for linking OW and GCC.
gcc vs g++ shouldn't matter

Andi B.

  • Hero Member
  • *****
  • Posts: 870
  • Karma: +14/-2
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #2 on: July 15, 2024, 09:04:07 am »
I tried various combinations of dllexport (which seems to be mandatory to export the symbol) and stdcall cdecl... But I ever end up with exporting _NdpTypes instead NdpTypes. I was under the impression that c++ don't add the _ but obviously I misinterpreted some stuff.

Another idea, is there any emx tool which can modify the exported symbols? Or add a new symbol to a dll which references to the orignal?

Btw. this all started cause I didn't manage to convince c++/linker to work with a .def file as it was used with icc or watcom. You know I'm not experienced with all this stuff so there is much guessing on my side.
« Last Edit: July 15, 2024, 09:11:45 am by Andi B. »

Paul Smedley

  • Hero Member
  • *****
  • Posts: 2283
  • Karma: +176/-0
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #3 on: July 15, 2024, 10:16:44 am »
Isn't it _System to use non-underscored variable names?

Dave Yeo

  • Hero Member
  • *****
  • Posts: 5083
  • Karma: +117/-1
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #4 on: July 15, 2024, 06:02:14 pm »
Isn't it _System to use non-underscored variable names?

Might be.

Dave Yeo

  • Hero Member
  • *****
  • Posts: 5083
  • Karma: +117/-1
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #5 on: July 15, 2024, 06:16:37 pm »
I tried various combinations of dllexport (which seems to be mandatory to export the symbol) and stdcall cdecl... But I ever end up with exporting _NdpTypes instead NdpTypes. I was under the impression that c++ don't add the _ but obviously I misinterpreted some stuff.

Another idea, is there any emx tool which can modify the exported symbols? Or add a new symbol to a dll which references to the orignal?

Btw. this all started cause I didn't manage to convince c++/linker to work with a .def file as it was used with icc or watcom. You know I'm not experienced with all this stuff so there is much guessing on my side.

You only need dllexport if you don't have the symbols in the def file. Traditionally, before we got dllexport, you hand wrote a DEF file including the exports, either by name or ordinal or you ran emxexp on the
object files and piped the results to the def file. Run emxexp with no parameters to see usage..
I've only done it the other way, pulling in symbols from a GCC DLL to a OW binary.
Note that with OW, you have to be careful to use the right calling convention to begin with, it defaults to its own calling convention which is incompatible with GCC DLLs, it uses registers instead of the stack.
See "Open Watcom 2.0 C/C++ Programmers Guide under Commonly Asked Questions, Converting to OpenWatcom C/C++, Conversion from IBM-compatible PC compilers.
In the case of porting from icc or OW, I simply edit the DEF, adding the underscores

Edit: You might also need the extern keyword
« Last Edit: July 15, 2024, 06:18:25 pm by Dave Yeo »

KO Myung-Hun

  • Newbie
  • *
  • Posts: 45
  • Karma: +6/-0
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #6 on: July 16, 2024, 02:06:56 am »
Hi/2.

You can append `asm("variable_name")' to a variable declaration like:

Quote
__attribute__ ((dllexport)) extern const char *NdpTypes[] asm("NdpTypes");

You can use `__asm__' instead of `asm'.

For details, see http://trac.netlabs.org/libc/wiki/Faq#Howtodeclareavariablesoitwontgetanunderscore and https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html.

Lars

  • Hero Member
  • *****
  • Posts: 1367
  • Karma: +70/-0
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #7 on: July 16, 2024, 07:47:31 am »
OS/2 32-bit calling convention for public interfaces should always be syscall in order to avoid all these name decoration problems. Depending on compiler, this is _System or syscall or _syscall and proper header files for the compiler will map that to APIENTRY and also EXPENTRY.
Note: OS/2 16-bit calling convention is Pascal. There are technical reason for using Pascal in 16-bit code (you need a calling convention where the called function cleans up the stack in order to support call gates. And Pascal is a calling convention that expects the called function to clean up the stack). Pascal uppercases all symbols ...

As has been stated, the calling convention also applies to data variables (only for the naming, of course. Nothing is called from a data variable). And before you start fuzzing with tools,aybe the easiest way is to use:
EXPENTRY char * myGlobalVar;
or (I cannot remember)
char * EXPENTRY myGlobalVar;

and to then use the def file to export a symbol named myGlobalVar because the syscall calling convention neither decorates names (as C callin convention does) nor uppercases names (as the Pascal calling convention does).
It will leave the symbol name untouched.

It should be obvious that on the accessing side, you will need to also properly use the calling convention:
extern char EXPENTRY *theGlobalVar;
« Last Edit: July 16, 2024, 08:18:26 am by Lars »

Andi B.

  • Hero Member
  • *****
  • Posts: 870
  • Karma: +14/-2
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #8 on: July 17, 2024, 07:41:19 pm »
Hi/2.

You can append `asm("variable_name")' to a variable declaration like:

Quote
__attribute__ ((dllexport)) extern const char *NdpTypes[] asm("NdpTypes");

You can use `__asm__' instead of `asm'.

For details, see http://trac.netlabs.org/libc/wiki/Faq#Howtodeclareavariablesoitwontgetanunderscore and https://gcc.gnu.org/onlinedocs/gcc/Asm-Labels.html.

Thank you so much. This works, though I've to test even more.

Quote
_System
I get -
Code: [Select]
./h/ndextpl2.h:354:102: error: '__system__' was not declared in this scope
  354 | extern const char __attribute__((visibility("default"))) __attribute__ ((dllexport)) __attribute__ ((_System))*NdpTypes[];
with that. As with a lot of other combinations I tried.

.def file - the whole thing started as I could not find out how to convince
Code: [Select]
g++.exe (GCC) 9.2.0 20190812 (OS/2 RPM build 9.2.0-5.oc00)to use a .def file. So I thought it's more clear to put such thing straight into the code.

Thanks for all inputs.

Dave Yeo

  • Hero Member
  • *****
  • Posts: 5083
  • Karma: +117/-1
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #9 on: July 18, 2024, 01:05:52 am »

.def file - the whole thing started as I could not find out how to convince
Code: [Select]
g++.exe (GCC) 9.2.0 20190812 (OS/2 RPM build 9.2.0-5.oc00)to use a .def file. So I thought it's more clear to put such thing straight into the code.

Just add the def file to the linker line. Should also use -Zomf for linking to use a native linker and be able to debug.
Code: [Select]
g++ -Zdll -Zomf foo.def foo.o -o foo.dll
or for an executable,
Code: [Select]
g++ -Zomf bar.def bar.o -o bar.exe
Add -Zmap to produce a map file, -Zhigh-mem to use high memory, -g for debug symbols etc.

BTW, libc seems to use _system, not __system__

Andi B.

  • Hero Member
  • *****
  • Posts: 870
  • Karma: +14/-2
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #10 on: July 18, 2024, 09:45:17 am »
Quote
BTW, libc seems to use _system, not __system__
I also wondered where the leading and trailing __ coming from. You see above I used _System which something magically changed to __system__. The same goes with other such attributes. cdecl is converted to __cdecl__ and so on IIRC. If an attribute is not recognized f.i. 'system' the error message is different.


Dave Yeo

  • Hero Member
  • *****
  • Posts: 5083
  • Karma: +117/-1
    • View Profile
Re: GCC/G++ - how to export global variable without underscore?
« Reply #11 on: July 18, 2024, 05:13:30 pm »
Seems __system__ etc are internal to GCC, no idea what is happening with the errors.
Are you including os2.h? If not, I think you have to include unidef.h for _system
BTW, even using dllexport, you still need a DEF file, just without any exports. Still need the NAME etc to be passed to the linker