LINUX.ORG.RU

Структуры, указатели, типы.

 , , ,


0

1

Пишу маленькую библиотеку. Она использует libxml2. В хидере определил структуру. Цель: скрыть типы данных libxml2.

struct fb2_str_file {
    void *doc;
    void *cur;
};

Указатель на нее программа-тестер кидает либе. В либе в свою очередь открываю файл

int fb2_open_file(const char *docname, struct fb2_str_file *file) {
    file->doc = xmlParseFile(docname);

Без ошибок. Получаю ноду

file->cur = xmlDocGetRootElement(file->doc);

После чего вот здесь начинаются непонятки.

if (xmlStrcmp((*file->cur)->name, (const xmlChar *) "FictionBook")) {

На этой строчке gcc пишет что

warning: dereferencing ‘void *’ pointer [enabled by default]
error: void value not ignored as it ought to be

Значит, file это указатель на структуру, в которой указатель на структуру с полем name. Вроде конструкция правильная. Но компилятор хочет чтобы я привел void к типу. Я не догоняю как это сделать.


Ответ на: комментарий от beastie

Я бы хотел так сделать, но не знаю как экспортировать типы. Дело в том, что если я буду использовать в этой структуре своей библиотеки типы libxml2, то придется компилировать любую программу не только с моей библиотекой, но и с libxml. А мне хочется, чтобы моя либа была слинкована с libxml а юзерская программа только с моей либой. или я хочу чего-то очень странного?

Gregon
() автор топика

нельзя одновременно скрыть тип данных и пользоваться его полями.

Значит, file это указатель на структуру, в которой указатель на структуру с полем name

«на структуру с полем name» - такого в объявлении структуры нет.

anonymous
()
Ответ на: комментарий от beastie

Блин, я оказывается неправильно кастовал тип. Ошибка была в том, что я постоянно пихал (xmlNodePtr *) в разных вариациях и удивлялся, почему мне говорят что cur это не struct.

Gregon
() автор топика
Ответ на: комментарий от Gregon

Да, странного. Либо я старый осёл, либо либы между собой не линкуются. Линковать юзерскую программу с libxml так или иначе прийдётся.

Тут два варианта: либо писать обёртки для «чужих» структур, либо использовать opaque pointer. Второй вариант imho в данном случае предпочтительней.

beastie ★★★★★
()
Ответ на: комментарий от anonymous

нельзя одновременно скрыть тип данных и пользоваться его полями.

Именно поэтому я леплю костыли вокруг void *.

«на структуру с полем name» - такого в объявлении структуры нет.

Есть, xmlDocGetRootElement возвращает указатель на структуру с таким полем.

Gregon
() автор топика
Ответ на: комментарий от Gregon

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

xmlStrcmp(((xmlNode *)(file->cur))->name…

а ещё, можно так написать:

struct fb2_str_file_private {
    xmlDoc *doc;
    xmlNode *cur;
};
...
fb2_str_file_private* pfile = (fb2_str_file_private*)file;
if (xmlStrcmp((*pfile->cur)->name, (const xmlChar *) "FictionBook")) {

anonymous
()
Ответ на: комментарий от Gregon

Есть, xmlDocGetRootElement возвращает указатель на структуру с таким полем.

да, но потом он приводится к типу void* и все, больше доступа к полям структуры не имеешь. вернуть доступ к полям можно только приведением типа.

anonymous
()
Ответ на: комментарий от beastie

Линковать юзерскую программу с libxml так или иначе прийдётся.

А какая общая практика? То есть если есть либа foo, ее использует либа bar а либу bar использует программа, то программу как правило всегда линкуют с обоими либами?

Gregon
() автор топика
Ответ на: комментарий от anonymous

Я правильно понял, указатель на структуру с void-ами кастуется в указатель на структуру где все мемберы были приведены к нужным типам? Интересно, попробую использовать.

Gregon
() автор топика
Ответ на: комментарий от Gregon

http://www.delorie.com/gnu/docs/libtool/libtool_39.html ← более развёрнутый ответ.

Кратко: общего подхода нет. Зависит от системы. Обычно библиотеки самодостаточны. Если нет → программы линкуются со всеми зависимостями, что может быть автоматизировано. Это в принципе и есть общая практика.

UPD: альтернативно, твою библиотеку можно _статически_ связать с зависимостями, тогда они будут включены в твою библиотеку. Это скорей всего как раз то, что ты хочешь. (Надеюсь я тут ничего не напутал — давно библиотек не строил.)

beastie ★★★★★
()
Последнее исправление: beastie (всего исправлений: 2)
Ответ на: комментарий от beastie

статически

Э-э, нет. Я просто вообще никогда не строил библиотек и не вкурсе тонкостей. Поэтому и решил опрометчиво, что нужно скрывать типы данных библиотек, которые являются непрямыми зависимостями.

Gregon
() автор топика

Пофиксил типы в структуре на родные для libxml. Полет отличный. Спорная строчка теперь выглядит как file->cur->name и радует глаз.

Gregon
() автор топика
Ответ на: комментарий от beastie

Либо я старый осёл, либо либы между собой не линкуются.

Динамические очень даже линкуются. И это весьма удобная фича, позволяющая добиться того, что и хочет ТС.

const86 ★★★★★
()
Ответ на: комментарий от Gregon

Поэтому и решил опрометчиво, что нужно скрывать типы данных библиотек, которые являются непрямыми зависимостями.

Не то чтобы обязательно нужно, но не лишне. Например, я установил уже собранную твою либу и хочу собрать свою прогу с ней. Хорошо, если мне для этого не будет требоваться ставить хедеры libxml2.

В общем случае это решается убиранием определений структур с лишними подробностями из публичного хедера. Остаётся только объявление структуры и используются указатели на неё. В libxml2 и так только указатели. Если бы её функции опрерировали с struct xmlNode*, то ты мог бы в своём хедере объявить эту структуру и всё. Можно скопипастить typedef из libxml2, но это как бы не совсем хорошо тоже.

const86 ★★★★★
()

Используешь хидеры от libxml2 но у всех функций указываешь ключевое слово extern.

Использование же структур не обязывает статически линковать с либой, они для правильного определения смещений.

anonymous
()
Ответ на: комментарий от const86

Во, именно чего-то такого я и хотел.

Не понимаю, как убрать структуры из хедера. Только что наблюдал, у меня там сейчас в структуре другая структура. написал struct foo; сверху, а компилятор все равно ругается на incomplete type, если структура-в-структуре объявлена ниже общей структуры.

Gregon
() автор топика
Ответ на: комментарий от greek_31

Началось все неочевидно. Понадобилось распечатать fb2 книжку. Посмотрел в сторону конвертеров в лейтех, они все выглядели несколько заброшенными, да и я давно хотел прокачать скилл, вот и сел велосипедить. Пишу связку libfb2 + fb2tex. Библиотека нужна для абстракции от xml и конкретных особенностей фомата fb2.

Могу дать ссылку на гитхаб при условии сильно не бить за кривой код.

Gregon
() автор топика
Ответ на: комментарий от Gregon

Нет, не моё. Я пробовал писать редактор, но с gtk затыки напрягли и я забил.

greek_31 ★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.