www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Undefined references when linking to C library

reply Peter Federighi <pfederighi yahoo.com> writes:
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
Dec 22 2010
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 22 2010
parent reply Peter Federighi <pfederighi yahoo.com> writes:
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
Dec 23 2010
next sibling parent Jonathan M Davis <jmdavisProg gmx.com> writes:
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
Dec 23 2010
prev sibling next sibling parent =?UTF-8?B?IkrDqXLDtG1lIE0uIEJlcmdlciI=?= <jeberger free.fr> writes:
Peter Federighi wrote:
 Jonathan M Davis wrote:
 Did you wrap the C declarations in an extern(C) block? Without that, i=
t'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 porti=
on of - in
 not all of - your gpm.d file should likely be in extern(C).
=20 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 =
=2Edata
 /usr/lib64/gcc/x86_64-suse-linux/4.5/../../../../lib/libgpm.so: could n=
ot read
 symbols: Bad value
 collect2: ld returned 1 exit status
 --- errorlevel 1
=20
 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 succ=
essfully
 compiled other programs that use C libraries such as SDL and OpenGL (bo=
th via the
 Derelict2 modules).
=20
I think gpm_zerobased, _bpm_buf and _gpm_arg should be declared __gshared. Jerome --=20 mailto:jeberger free.fr http://jeberger.free.fr Jabber: jeberger jabber.fr
Dec 23 2010
prev sibling parent reply wrzosk <dprogr gmail.com> writes:
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.
Dec 23 2010
parent Peter Federighi <pfederighi yahoo.com> writes:
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
Dec 23 2010