Надо вызывать функцию g_fprintf (библиотека gtk)

Модератор: Модераторы разделов

Аватара пользователя
жучара
Сообщения: 1072
ОС: астралинукс

Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение жучара »

Друзья! Есть графическое приложение и в нём нужно просто-напросто кое-что написать в файл. Использую функцию g_fprintf (коль скоро приложение графическое, то всё должно быть графическим), но ничего не получается.

Код: Выделить всё

/* main.c */
#include <gtk/gtk.h>

int main ()
{
  FILE* fp = g_fopen ("foo.txt", "w");
  g_fprintf (fp, "Hello, world!");
  return 0;
}

Shell

$ gcc -I/usr/include/gtk-4.0 -I/usr/include/pango-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/harfbuzz -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/graphene-1.0 -I/usr/lib/x86_64-linux-gnu/graphene-1.0/include main.c -lglib-2.0
main.c: In function ‘main’:
main.c:5:14: warning: implicit declaration of function ‘g_fopen’; did you mean ‘fopen’? [-Wimplicit-function-declaration]
5 | FILE* fp = g_fopen ("foo.txt", "w");
| ^~~~~~~
| fopen
main.c:5:14: warning: initialization of ‘FILE *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
main.c:6:3: warning: implicit declaration of function ‘g_fprintf’; did you mean ‘vfprintf’? [-Wimplicit-function-declaration]
6 | g_fprintf (fp, "Hello, world!");
| ^~~~~~~~~
| vfprintf
$
Я и сам знаю, что функции fopen и vfprintf ЕСТЬ. Но мне нужные g_fopen и g_fprintf (Изначально, напомню, приложение графическое, а этот код вырожденный).

Shell

$ ./a.out
Ошибка сегментирования
$
Такие дела. Но пустой foo.txt всё ж таки создаётся:

Shell

$ ls -l foo.txt
-rw-r--r-- 1 user user 0 мая 2 00:47 foo.txt
$
ЧЯДНТ? Спасибо, кто откликнется. Debian 12.
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5393
ОС: Gentoo

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение /dev/random »

жучара писал(а):
02.05.2025 03:04
warning: implicit declaration of function ‘g_fopen’
Вы не включили заголовки от glib, только от gtk.

Upd: по приведённой вами же ссылке:
GLib.fprintf писал(а):glib/gprintf.h must be explicitly included in order to use this function.
А для g_fopen, насколько я помню, нужен glib/gstdio.h

Upd2: вообще, когда вы видите "implicit declaration", это значит вы либо опечатались в имени функции (не в вашем случае), либо забыли подключить какой-то заголовочник.
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1072
ОС: астралинукс

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение жучара »

/dev/random писал:
02.05.2025 07:52
жучара писал(а):
02.05.2025 03:04
warning: implicit declaration of function ‘g_fopen’
Вы не включили заголовки от glib, только от gtk.

Upd: по приведённой вами же ссылке:
GLib.fprintf писал(а):glib/gprintf.h must be explicitly included in order to use this function.
А для g_fopen, насколько я помню, нужен glib/gstdio.h

Upd2: вообще, когда вы видите "implicit declaration", это значит вы либо опечатались в имени функции (не в вашем случае), либо забыли подключить какой-то заголовочник.

Понятно. Обошёлся пока #include <glib/gstdio.h> Что же даёт #include <glib/gstdio.h>?

Код тот же, команда компиляции та же

1) НЕ ИСПОЛЬЗУЕМ #include <glib/gstdio.h>:

Shell

$ nm a.out | grep "U "
U g_fopen
U g_fprintf
U __libc_start_main@GLIBC_2.34
$
2) ИСПОЛЬЗУЕМ #include <glib/gstdio.h>:

Shell

$ nm a.out | grep "U "
U fopen@GLIBC_2.2.5
U g_fprintf
U __libc_start_main@GLIBC_2.34
$
То есть g_fopen подменяется на fopen@GLIBC_2.2.5 и это действительно всё решает. Удивительным образом решает. Итак,

1) ИСПОЛЬЗУЕМ #include <glib/gstdio.h>, компилим, командуем:

Shell

$ rm foo.txt && ./a.out
$
$ cat foo.txt
Hello, world!
$
Всё хорошо.

1) НЕ ИСПОЛЬЗУЕМ #include <glib/gstdio.h>, компилим, командуем:

Shell

$ rm foo.txt && ./a.out
Ошибка сегментирования
$
$ cat foo.txt
$
Не хорошо, но удивительно. Проблемная функция g_fopen СОЗДАЁТ ТАКИ файл foo.txt, но g_fprintf записать в него ничего не может. Видать g_fopen не даёт ей этого сделать потому, что g_fopen и вправду проблемная.

...В код g_fopen я не полез, но посмотрел, где она есть. Для этого убрал из командной строки опцию -lglib-2.0 и помимо предупреждений всяких при компиляции получил такое:

Shell

...
/usr/bin/ld: /tmp/cc4y0BeH.o: в функции «main»:
main.c:(.text+0x22): неопределённая ссылка на «g_fopen»
/usr/bin/ld: main.c:(.text+0x43): неопределённая ссылка на «g_fprintf»
collect2: error: ld returned 1 exit status
...
То есть тело g_fopen и g_fprintf присутствуют в файле /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.7400.6 (как я до него добрался- кто в теме, тот поймёт). И первая так написана, что её аж необходимо заменять.

Тот факт, что функция g_fopen есть в файле /usr/lib/x86_64-linux-gnu/libglib-2.0.so.0.7400.6 даёт нам понять, почему при компиляции нет ошибок линковщика- их и вправду нет. Линковщик просто проверяет наличие функций, а уж как они работают- дело десятое для него.
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3001
ОС: Gentoo

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение ormorph »

жучара писал(а):
03.05.2025 01:59
1) НЕ ИСПОЛЬЗУЕМ #include <glib/gstdio.h>, компилим, командуем:
Shell

$ rm foo.txt && ./a.out
Ошибка сегментирования
$
$ cat foo.txt
$
Не хорошо, но удивительно. Проблемная функция g_fopen СОЗДАЁТ ТАКИ файл foo.txt, но g_fprintf записать в него ничего не может. Видать g_fopen не даёт ей этого сделать потому, что g_fopen и вправду проблемная.

...В код g_fopen я не полез, но посмотрел, где она есть. Для этого убрал из командной строки опцию -lglib-2.0 и помимо предупреждений всяких при компиляции получил такое:
Используете древний компилятор, вот и получаете проблемы. Обычно на последних после удаления заголовочника с прототипом <glib/gstdio.h>, не должно собирать, а у вас собирает. Тут проблема в самом компиляторе, как он создаёт прототип для линковки. Я например такое не могу у себя реализовать. Тут фишка, что в заголовочнике есть строка:

Код: Выделить всё

#define g_fopen   fopen
Компилятор само собою подменяет это на fopen при наличии заголовочника, а при отсутствии пытается использовать функцию g_fopen из glib-2.0. А так обычно используется pkg-config(pkgconf), для сборки c glib-2.0:

Shell

$ gcc main.c -o main $(pkg-config --libs --cflags glib-2.0)
Могу предположить что функция из glib-2.0 работает неправильно и возвращает неправильный указатель на файловый дескриптор и т.п.. Ну и закрывать не помешало бы используя fclose(fp).
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3001
ОС: Gentoo

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение ormorph »

На своём компиляторе я смог собрать с функцией из glib-2.0, просто добавил строчки перед строкой #include <glib/gstdio.h>:

Shell

#define __GTK_DOC_IGNORE__
#define G_STDIO_WRAP_ON_UNIX
как результат:

Shell

U fclose@GLIBC_2.2.5
U g_fopen
U g_fprintf
Но у меня всё работает нормально, без заголовочника #include <glib/gstdio.h>, я вообще не могу собрать. Так что как у вас линкует компилятор без заголовочника #include <glib/gstdio.h>, кто его знает.
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1072
ОС: астралинукс

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение жучара »

ormorph
Ну понял. Вы то же, что и я написали, просто охарактерзовали работу моего компилятора как "неправильно" и "кто его знает". На счёт последнего- а чё ему не собирать, то если и g_fopen и g_fprintf есть? Об этом, я писал, кстати. То, что g_fopen такая, вряд ли компилятор (линковщик) в этом виноват- я тоже об этом писал.
Я ценю ваши оценки.
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5393
ОС: Gentoo

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение /dev/random »

жучара, для сборки нужна не только сама функция (где-то в библиотеках), но и её объявление, с типами параметров и возвращаемым типом (где-то в вашей программе или подключённых заголовочниках). Если объявления нет, то вызов приводит к появлению "неявного объявления" (о котором и было предупреждение), с типами параметров, взятыми из переданных в вызове аргументов, и возвращаемым типом int (всегда только int).
В вашем случае правильным объявлением было бы:
FILE *g_fopen(const char *, const char *);,
а неявное определение получается таким:
int g_fopen(const char *, const char *);.
В результате возвращаемый 64-битный указатель обрезается до 32-битного int, а потом вы этот int присваиваете как указатель (об этом другое предупреждение в логе). В результате вы получить-то этот FILE* получили, но половину битов занулили, и указывает этот указатель теперь не туда. И при попытке обратиться по нему функцией g_fprintf вы получаете сегфолт.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3001
ОС: Gentoo

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение ormorph »

жучара писал(а):
03.05.2025 12:23
То, что g_fopen такая, вряд ли компилятор (линковщик) в этом виноват- я тоже об этом писал.
Ну так /dev/random тут как раз и описал, что неправильно тип вункции получается, от этого неправильная адресация. Как результат g_fprintf, обращается совершенно к другому адресу. Но в принципе это можно было просмотреть если собрать с ключиком -E. Компилятор то не виноват, но и неправильно писать код без объявления прототипов. Видно по этому последние версии не позволяют собрать без заголовочников, точнее объявленных прототипов.
Спасибо сказали:
Аватара пользователя
жучара
Сообщения: 1072
ОС: астралинукс

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение жучара »

ormorph писал(а):
03.05.2025 14:04
жучара писал(а):
03.05.2025 12:23
То, что g_fopen такая, вряд ли компилятор (линковщик) в этом виноват- я тоже об этом писал.
Ну так /dev/random тут как раз и описал, что неправильно тип вункции получается, от этого неправильная адресация. Как результат g_fprintf, обращается совершенно к другому адресу. Но в принципе это можно было просмотреть если собрать с ключиком -E. Компилятор то не виноват, но и неправильно писать код без объявления прототипов. Видно по этому последние версии не позволяют собрать без заголовочников, точнее объявленных прототипов.
Ну да. Как раз-таки это ответ на вопрос
ormorph писал(а):
03.05.2025 11:51
Так что как у вас линкует компилятор без заголовочника #include <glib/gstdio.h>, кто его знает.
...Я такого вопроса не ставил, мне было всё понятно (понятно неправильно, естественно). Я думал, что всё равно где-то прототип есть где то чёрт его знает где, только он неправильный и из-за этого ругань вся. Или другой вариант: если прототипа нет, то умный компилятор по вызову функции сам умеет ПРАВИЛЬНЫЙ прототип, а плохая работа приложения лишь следствие корявой функции g_fopen. А ничего подобного- с правильными самописными прототипами всё отрабатывает на ура, даже предупреждений никаких нет.

Код: Выделить всё

#include <gtk/gtk.h>

FILE *g_fopen(const char *, const char *);
gint g_fprintf (FILE*, const gchar* );

int main ()
{
  FILE* fp = g_fopen ("foo.txt", "w");
  g_fprintf (fp, "Hello, world!\n");
  return 0;
}

...Так что да- умолчальный прототип с умолчальными значениями.
Я просто читаю маны.
Спасибо сказали:
Аватара пользователя
ormorph
Сообщения: 3001
ОС: Gentoo

Re: Надо вызывать функцию g_fprintf (библиотека gtk)

Сообщение ormorph »

жучара писал(а):
03.05.2025 14:41
Я думал, что всё равно где-то прототип есть где то чёрт его знает где, только он неправильный и из-за этого ругань вся.
Я только недавно натыкался на пример, где точно так же не созданы прототипы в заголовочниках, а тем не менее на старых компиляторах это собиралось. Т.е. компилятор сам раньше создавал прототипы во время сборки. Сейчас сборка таких проектов заканчивается ошибкой. Само собою так писать неправильно, но тем не менее такие проекты раньше создавались и работали, теперь их просто не собрать. Тут я точно знаю что прототип ни где не был создан.
Спасибо сказали: