0

I am developing some library using Gtkmm4. This libraries purpose is to replace the removed API of Gtkmm3 (such as Gtk::Window::move). Especially for this particular function, i need to use gdk_x11_surface_move. The linker says undefined reference to gdk_x11_surface_move. My library libgdp.so links to following Gtk libraries:

$ ldd libgdp.so.1 | grep gtk
    libgtkmm-4.0.so.0 => /home/user/.local/built/lib/libgtkmm-4.0.so.0 (0x00007f981fb5a000)
    libgtk-4.so.1 => /home/user/.local/built/lib/libgtk-4.so.1 (0x00007f981d57a000)

And in that libgtk-4.so.1, gdk_x11_surface_move is defined:

$ nm  /home/user/.local/built/lib/libgtk-4.so.1 --defined-only | grep x11_surface_move
0000000000461cc0 t gdk_x11_surface_move
0000000000462730 T gdk_x11_surface_move_to_current_desktop
0000000000462540 T gdk_x11_surface_move_to_desktop

Interesting / important might be following output, where gdk_x11_surface_move is not present:

$ nm -D /home/papa/.local/built/lib/libgtk-4.so.1 --defined-only | grep x11_surface_move
0000000000462730 T gdk_x11_surface_move_to_current_desktop
0000000000462540 T gdk_x11_surface_move_to_desktop

In my code i am using gdk_x11_surface_move like this:

window.cpp

#include <window.hpp>

...

void Window::move(int x, int y) {
    auto surface = this->get_surface().get();
    gdk_x11_surface_move(surface, x, y);
}

...

window.hpp

...

extern "C" {
    void gdk_x11_surface_move(Gdk::Surface *surface, int x, int y);
}

...

I just do not understand why I cannot use that function in my library, even though it is defined / available in the Gtk library. Can you find a solution ? If you need any more details, please let me know by writing me a comment !

EDIT The library gets linked with following command:

/bin/bash ./libtool  --tag=CXX --silent  --mode=link g++  -g -O2 -version-info 1:0: -L/home/user/.local/built/lib  -o libgdp.la -rpath /home/user/.local/built/lib src/libgdp_la-logger.lo src/libgdp_la-window.lo src/libgdp_la-utils.lo -L/home/user/.local/built/lib -lgtkmm-4.0 -lpangomm-2.48 -lgiomm-2.68 -lglibmm-2.68 -lcairomm-1.16 -lsigc-3.0 -lgtk-4 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -lgdk_pixbuf-2.0 -lcairo-gobject -lcairo -lgraphene-1.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -L/home/user/.local/built/lib

and the application with the following command which throws the error:

g++  -g -O2  -L/home/user/.local/built/lib  -o gdp-screenshot src/gdp_screenshot-main.o src/gdp_screenshot-application.o src/gdp_screenshot-prefswindow.o src/gdp_screenshot-savewindow.o src/gdp_screenshot-screenshot.o -L/home/user/.local/built/lib -L/home/user/Programme/c++/GDP-Gtk/libgdp/.libs -lgdp -lgtkmm-4.0 -lpangomm-2.48 -lgiomm-2.68 -lglibmm-2.68 -lcairomm-1.16 -lsigc-3.0 -lgtk-4 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -lgdk_pixbuf-2.0 -lcairo-gobject -lcairo -lgraphene-1.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lX11 -L/home/user/.local/built/lib -lgtkmm-4.0 -lpangomm-2.48 -lgiomm-2.68 -lglibmm-2.68 -lcairomm-1.16 -lsigc-3.0 -lgtk-4 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -lgdk_pixbuf-2.0 -lcairo-gobject -lcairo -lgraphene-1.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -L/home/user/.local/built/lib -lfribidi -L/home/user.local/built/lib -lglibmm-2.4 -lgobject-2.0 -lglib-2.0 -lsigc-2.0 -L/home/user/.local/built/lib
/home/user/Programme/c++/GDP-Gtk/libgdp/.libs/libgdp.so: warning: undefined reference to »gdk_x11_surface_move(Gdk::Surface*, int, int)«
collect2: error: ld returned 1 exit status
Makefile:525: recipe for target 'gdp-screenshot' failed

and in fact is thrown in the phase where the application that uses the libgdp.so library is linked. The library itself compiles and links fine.

TheEagle
  • 5,808
  • 3
  • 11
  • 39
  • 1
    Please paste the exact error. – Useless Feb 15 '21 at 18:29
  • @Useless done . – TheEagle Feb 15 '21 at 18:34
  • 2
    And I assume `/home/papa/...` and `/home/user/...` are in reality the same path? – Useless Feb 15 '21 at 18:49
  • @Useless exactly, i forget to replace that ! :( and sorry for the long answer time. – TheEagle Feb 15 '21 at 20:35
  • `gdk_x11_surface_move` looks like a C function, your linker complains about a C++ function. Perhaps you forgot `extern "C"` somewhere. – n. m. could be an AI Feb 15 '21 at 21:04
  • @n.'pronouns'm. hm, `gdk_x11_surface_move` __is__ a C function, i will try that out ! – TheEagle Feb 15 '21 at 21:05
  • @n.'pronouns'm. As the Gtk headers provide no definition of `gdk_x11_surface_move`, I defined it myself. Wrapping this definition into `extern "C"` changes nothing (i added the relevant parts of the implementation and header file) – TheEagle Feb 15 '21 at 21:16
  • Since the error is in libgdp.so, I suggest using nm again to examine its symbol table. There should be an `gdk_x11_surface_move` entry which is undefined. If it's still mangled, something is ignoring your extern C. – Useless Feb 16 '21 at 00:25
  • @Useless `nm /home/user/.local/built/lib/libgdp.so.1 | grep gdk` prints nothing ! – TheEagle Feb 16 '21 at 00:33
  • Is the error message still showing the function arguments? Normally there are no arguments known to the linker (that is, function name is not mangled) when the function is `extern "C"`. Unless I'm missing something about the new generation of linkers, that is. – n. m. could be an AI Feb 16 '21 at 04:59
  • *`nm` ... prints nothing* Try `nm -D`. – n. m. could be an AI Feb 16 '21 at 04:59
  • Also relevant https://stackoverflow.com/questions/45135/why-does-the-order-in-which-libraries-are-linked-sometimes-cause-errors-in-gcc – n. m. could be an AI Feb 16 '21 at 05:01
  • @n.'pronouns'm. ǹm -D /home/user/.local/built/lib/libgdp.so.1 | grep gdk` prints nothin either. Relevant might be that the `libgdp` library and the application that uses it are both built with autotools, so i do not think it's an issue in the order the libraries are linked (Autotools should handle that), but i added both linking commands to my question. – TheEagle Feb 16 '21 at 11:23
  • @n.'pronouns'm. While waiting for your answer i tried `nm -D` on the gtk library, whose interesting output you can find in my question ! – TheEagle Feb 16 '21 at 11:50
  • This means that `gdk_x11_surface_move` is not exported from this library. – n. m. could be an AI Feb 16 '21 at 17:46
  • @n.'pronouns'm. okay, is there a way i can use it all the same ? If not, i will just copy the code from the original gtk sources into my library (defined that function myself). – TheEagle Feb 16 '21 at 17:47
  • No I don't think it can be used directly, unless you link with a static library (or copy the code). – n. m. could be an AI Feb 16 '21 at 18:54
  • @n.'pronouns'm. Thanks, you helped me a lot ! – TheEagle Feb 16 '21 at 19:23

1 Answers1

2

I just do not understand why I cannot use that function in my library, even though it is defined / available in the Gtk library.

$ nm /home/user/.local/built/lib/libgtk-4.so.1 --defined-only | grep x11_surface_move
0000000000461cc0 t gdk_x11_surface_move

You are correct that the function is defined in libgtk-4.so.1, but you are mistaken in that it is available: t in nm output means it's a local function. Such functions can't be called from outside.

There are a few reasons why a function may get local linkage:

  1. the function is declared static in the file where it is defined.
  2. the function is global, but is hidden at compile (-fvisibility=hidden) or link time (using linker version script).

The fix depends on why the function is local. For 1) above, removing static qualifier will do. For 2), you may need to add __attribute__((visibility("default"))), or you may need to edit the linker version script.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362