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

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

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

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.

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