Почему я не могу использовать связанную функцию?

#c #shared-libraries #dynamic-linking #gtkmm

#c #совместно используемые библиотеки #динамическое связывание #gtkmm

Вопрос:

Я разрабатываю некоторую библиотеку, используя Gtkmm4. Цель этой библиотеки — заменить удаленный API Gtkmm3 (например, Gtk::Window::move ). Особенно для этой конкретной функции мне нужно использовать gdk_x11_surface_move . Компоновщик указывает неопределенную ссылку на gdk_x11_surface_move . Моя библиотека libgdp.so ссылается на следующие библиотеки Gtk:

 $ 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)
 

И в этом libgtk-4.so.1 gdk_x11_surface_move определяется:

 $ 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
 

Интересным / важным может быть следующий вывод, которого gdk_x11_surface_move нет:

 $ 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
 

В моем коде я использую gdk_x11_surface_move так:

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);
}

...
 

Я просто не понимаю, почему я не могу использовать эту функцию в своей библиотеке, хотя она определена / доступна в библиотеке Gtk. Можете ли вы найти решение? Если вам нужна дополнительная информация, пожалуйста, дайте мне знать, написав мне комментарий!

РЕДАКТИРОВАТЬ Библиотека связывается со следующей командой:

 /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
 

и приложение со следующей командой, которая выдает ошибку:

 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
 

и фактически выбрасывается на этапе, когда приложение, использующее libgdp.so библиотеку, связано. Сама библиотека компилируется и связывается нормально.

Комментарии:

1. Пожалуйста, вставьте точную ошибку.

2. @Бесполезно сделано.

3. И я предполагаю /home/papa/... , что и /home/user/... на самом деле это один и тот же путь?

4. @Точно бесполезно, я забыл заменить это! 🙁 и извините за долгое время ответа.

5. gdk_x11_surface_move похоже на функцию C, ваш компоновщик жалуется на функцию C . Возможно, вы extern "C" где-то забыли.

Ответ №1:

Я просто не понимаю, почему я не могу использовать эту функцию в своей библиотеке, хотя она определена / доступна в библиотеке Gtk.

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

Вы правы в том, что функция определена в libgtk-4.so.1 , но вы ошибаетесь в том, что она доступна: t в nm выводе означает, что это локальная функция. Такие функции не могут быть вызваны извне.

Есть несколько причин, по которым функция может получить локальную связь:

  1. функция объявляется static в файле, где она определена.
  2. функция является глобальной, но скрыта во время компиляции ( -fvisibility=hidden ) или компоновки (с использованием сценария компоновщика).

Исправление зависит от того, почему функция является локальной. Для 1) выше подойдет удаление static квалификатора. Для 2), возможно, вам потребуется добавить __attribute__((visibility("default"))) или отредактировать сценарий компоновочной версии.