Thread overview
Undefined references when linking to C library
Dec 23, 2010
Peter Federighi
Dec 23, 2010
Jonathan M Davis
Dec 23, 2010
Peter Federighi
Dec 23, 2010
Jonathan M Davis
Dec 23, 2010
Jérôme M. Berger
Dec 23, 2010
wrzosk
Dec 24, 2010
Peter Federighi
December 23, 2010
Hello all.

I'm writing a simple terminal game (that will eventually be turned into a simple SDL game) and thought I would add mouse support via libgpm.  So, I converted gpm.h into gpm.d.  Perhaps I didn't do this correctly because I get several undefined references when trying to link.

Here's an example:
The original gpm.h says:
extern int gpm_zerobased;
extern unsigned char    _gpm_buf[];
extern unsigned short * _gpm_arg;

My gpm.d says:
extern int gpm_zerobased;
extern char*  _gpm_buf;
extern ushort* _gpm_arg;

When running 'dmd gev.d gpm.d -L-lgpm', I get:
gpm.d:(.text._D3gpm15Gpm_DrawPointerFiiiZv+0x12): undefined reference to
`_D3gpm8_gpm_bufPa'
gpm.d:(.text._D3gpm15Gpm_DrawPointerFiiiZv+0x26): undefined reference to
`_D3gpm13gpm_zerobasedi'
gpm.d:(.text._D3gpm15Gpm_DrawPointerFiiiZv+0x34): undefined reference to
`_D3gpm8_gpm_argPt'

Does anyone have any ideas?

Thank you,
- Peter
December 23, 2010
On Wednesday 22 December 2010 19:25:35 Peter Federighi wrote:
> Hello all.
> 
> I'm writing a simple terminal game (that will eventually be turned into a simple SDL game) and thought I would add mouse support via libgpm.  So, I converted gpm.h into gpm.d.  Perhaps I didn't do this correctly because I get several undefined references when trying to link.
> 
> Here's an example:
> The original gpm.h says:
> extern int gpm_zerobased;
> extern unsigned char    _gpm_buf[];
> extern unsigned short * _gpm_arg;
> 
> My gpm.d says:
> extern int gpm_zerobased;
> extern char*  _gpm_buf;
> extern ushort* _gpm_arg;
> 
> When running 'dmd gev.d gpm.d -L-lgpm', I get:
> gpm.d:(.text._D3gpm15Gpm_DrawPointerFiiiZv+0x12): undefined reference to
> `_D3gpm8_gpm_bufPa'
> gpm.d:(.text._D3gpm15Gpm_DrawPointerFiiiZv+0x26): undefined reference to
> `_D3gpm13gpm_zerobasedi'
> gpm.d:(.text._D3gpm15Gpm_DrawPointerFiiiZv+0x34): undefined reference to
> `_D3gpm8_gpm_argPt'
> 
> Does anyone have any ideas?

Did you wrap the C declarations in an extern(C) block? Without that, it's going to think that your variables are D variables not C variables. The same goes for any functions - _especially_ for the functions. In fact, a large portion of - in not all of - your gpm.d file should likely be in extern(C).

You can try htod ( http://www.digitalmars.com/d/2.0/htod.html ) and see what it creates. It won't necessarily be correct, but it might be, and it might give you a better idea of where you screwed up. It's a Windows program, but it will run in wine.

- Jonathan M Davis
December 23, 2010
Jonathan M Davis wrote:
> Did you wrap the C declarations in an extern(C) block? Without that, it's going to think that your variables are D variables not C variables. The same goes for any functions - _especially_ for the functions. In fact, a large portion of - in not all of - your gpm.d file should likely be in extern(C).

I tried "extern (C)" for the whole module and individually.  I get the following
error:
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld:
_gpm_arg: TLS reference in gev.o mismatches non-TLS definition in
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so section .data
/usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so: could not read
symbols: Bad value
collect2: ld returned 1 exit status
--- errorlevel 1

Is this a 32/64 bit issue?  I have both versions of libgpm installed.  Those file paths are obtuse, but they do point to the 32 bit libraries.  I've successfully compiled other programs that use C libraries such as SDL and OpenGL (both via the Derelict2 modules).

I also tried htod and compared the output with what I wrote.  The differences are inconsequential.

Thank you,
- Peter Federighi
December 23, 2010
On Thursday 23 December 2010 11:38:28 Peter Federighi wrote:
> Jonathan M Davis wrote:
> > Did you wrap the C declarations in an extern(C) block? Without that, it's going to think that your variables are D variables not C variables. The same goes for any functions - _especially_ for the functions. In fact, a large portion of - in not all of - your gpm.d file should likely be in extern(C).
> 
> I tried "extern (C)" for the whole module and individually.  I get the
> following error:
> /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld:
> _gpm_arg: TLS reference in gev.o mismatches non-TLS definition in
> /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so section
> .data /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so:
> could not read symbols: Bad value
> collect2: ld returned 1 exit status
> --- errorlevel 1
> 
> Is this a 32/64 bit issue?  I have both versions of libgpm installed. Those file paths are obtuse, but they do point to the 32 bit libraries. I've successfully compiled other programs that use C libraries such as SDL and OpenGL (both via the Derelict2 modules).
> 
> I also tried htod and compared the output with what I wrote.  The differences are inconsequential.

Yeah. It looks like the compiler is finding the 64-bit versions rather than the 32-bit versions. How to fix that will likely depend on the libraries in question and on how your system is set up. Obviously, a 32-bit chroot environment would fix the problem, but that's also obviously not a pleasant, or even necessarily simple, solution.

I'm not really all that well-versed in dealing with linking issues like this, but I'd say that either the compiler is just not finding the 32-bit versions, because of a messed up or missing path, or you need to be linking separately because you're on a 64-bit system (which I don't _think_ is the case, but it might be). Regardless, you can try compiling all of the code with -c and then linking it with gcc directly (probably with -m32).

Unfortunately, while I do run a 64-bit environment, due to problems with Arch and multilib systems, I've generally had to run dmd in a chrooted environment, and you don't have to deal with the 32-bit vs 64-bit issues with that, so I don't have much experience with this sort of problem. Regardless, I'll be very glad when the 64-bit port of dmd is completed.

- Jonathan M Davis
December 23, 2010
Peter Federighi wrote:
> Jonathan M Davis wrote:
>> Did you wrap the C declarations in an extern(C) block? Without that, it's going to think that your variables are D variables not C variables. The same goes for any functions - _especially_ for the functions. In fact, a large portion of - in not all of - your gpm.d file should likely be in extern(C).
> 
> I tried "extern (C)" for the whole module and individually.  I get the following
> error:
> /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld:
> _gpm_arg: TLS reference in gev.o mismatches non-TLS definition in
> /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so section .data
> /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so: could not read
> symbols: Bad value
> collect2: ld returned 1 exit status
> --- errorlevel 1
> 
> Is this a 32/64 bit issue?  I have both versions of libgpm installed.  Those file paths are obtuse, but they do point to the 32 bit libraries.  I've successfully compiled other programs that use C libraries such as SDL and OpenGL (both via the Derelict2 modules).
> 
	I think gpm_zerobased, _bpm_buf and _gpm_arg should be declared
__gshared.

		Jerome
-- 
mailto:jeberger@free.fr
http://jeberger.free.fr
Jabber: jeberger@jabber.fr



December 23, 2010
On 23.12.2010 20:38, Peter Federighi wrote:
> Jonathan M Davis wrote:
>> Did you wrap the C declarations in an extern(C) block? Without that, it's going
>> to think that your variables are D variables not C variables. The same goes for
>> any functions - _especially_ for the functions. In fact, a large portion of - in
>> not all of - your gpm.d file should likely be in extern(C).
>
> I tried "extern (C)" for the whole module and individually.  I get the following
> error:
> /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../x86_64-suse-linux/bin/ld:
> _gpm_arg: TLS reference in gev.o mismatches non-TLS definition in
> /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so section .data
> /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so: could not read
> symbols: Bad value
> collect2: ld returned 1 exit status
> --- errorlevel 1
>
> Is this a 32/64 bit issue?  I have both versions of libgpm installed.  Those file
> paths are obtuse, but they do point to the 32 bit libraries.  I've successfully
> compiled other programs that use C libraries such as SDL and OpenGL (both via the
> Derelict2 modules).
>
> I also tried htod and compared the output with what I wrote.  The differences are
> inconsequential.
>
> Thank you,
> - Peter Federighi

I've had simmilar issue a few days ago. The problem is that global values from C should be marked shared in D

extern int val; -> extern (C) shared int val;

or maybe __gshared. Both makes linking stage finishes with success.
December 24, 2010
wrzosk wrote:
> I've had simmilar issue a few days ago. The problem is that global values from C
should be marked shared in D
> extern int val; -> extern (C) shared int val;
> or maybe __gshared. Both makes linking stage finishes with success.

Jerome M. Berger wrote:
> I think gpm_zerobased, _bpm_buf and _gpm_arg should be declared __gshared.

Indeed.  So I added a bunch of "__gshared"s to all the variables and it compiles and links.  Yah!  I just have to remember to declare handler functions with extern (C), otherwise the program will segfault once the handler returns.

Where should I post/upload the files that I converted?  There are a whole two of them:  One is gpm.h which is specific to libgpm.  The other is paths.h which I was surprised to find not already available.  I would assume that it should be available as std.c.linux.paths or core.sys.posix.paths.  Also, should the files end with .d or .di  I may be the only person who wants to use libgpm with D, but I figure it should be available just in case.

Thank you all for your help.
- Peter Federighi