C++ undefined reference to ...

Изображение пользователя nitrofox.

Я захотел воспользоваться одной библиотекой. При компиляции проекта линковщик мне заявил
undefined reference to `ddcci_probe()'
В С++ есть какие то тонкости?
Для теста я написал маленькую программку

В то же время проект на С нормально компилируется

Не могу понять почему..
0
fox4 - 19 Июль, 2016 - 19:42
Изображение пользователя fox4.

В первом варианте ( С++ ) у вас
monitorlist* dd
во втором ( С )
struct monitorlist* dd;
Думаю в этом проблема.
И ещё я сомневаюсь что в вашей библиотеке ddccontrol
monitorlist
определён как класс но думаю что его надо инициализировать через оператор
new()
раз вы создали указатель
monitorlist* dd;

0
nitrofox - 19 Июль, 2016 - 20:29
Изображение пользователя nitrofox.

Я как понял функция ddcci_probe() возвращает указатель на структуру(и надеюсь NULL когда список пуст). Так что выделения памяти должна делать ddcci_probe(). А освобождать ddcci_free_list(dd)( =) наверное.. И еще жесткая ошибка я тут всегда null передаю в ddcci_free_list(dd) так что тут утечка.).
Но это мелочи. Я копирую С код в проект C++(Созданный Qt creator) и все равно получаю ошибку линковки

С++

С

0
fox4 - 19 Июль, 2016 - 20:46
Изображение пользователя fox4.

Ну правильно получаете на сколько мне помнится все описания структур и классов в C++ должны быть в *.h файлах (объявления) а вот непосредственно реализация в *.cpp а у вас похоже винегрет :-) вот компоновщик и возмущается...
Дело в том что он по "хедерам вычисляет кому, сколько и где отвести памяти".
Если мне память не изменяет уж простите за тавтологию.

0
nitrofox - 19 Июль, 2016 - 21:41
Изображение пользователя nitrofox.

В хейдере описаны эти функции и структуры. #include <ddccontrol/ddcci.h>
Реализованы они в библиотеке libddccontrol.so | libddccontrol.a. (apt install libddccontrol-dev)

Как правильно воспользоваться этой библиотекой в моей программе?

0
fox4 - 19 Июль, 2016 - 22:13
Изображение пользователя fox4.

Если ваша программа написана на С++ но должна вызывать С функции то обычно пишут wrapper библиотеки так проще хоть и появляются накладные расходы.
Создайте класс типа "ddccontrol" в конструкторе сделайте
struct monitorlist* dd;
    dd = ddcci_probe();

возможно какие то поля структуры имеет смысл скопировать в переменные класса
в деструкторе
ddcci_free_list(dd);
ну а в других методах-класса можно оставшиеся функции вызывать тут всё зависит от вашей фантазии и необходимости...

0
nitrofox - 19 Июль, 2016 - 23:21
Изображение пользователя nitrofox.

Создал хедер
struct MonitorList{
public:
    MonitorList();
private:
    struct monitorlist* pListMonitor;
};

и cpp
#include "monitorlist.h"
MonitorList::MonitorList(){
    pListMonitor = ddcci_probe();
}

и main.cpp
#include "monitorlist.h"
int main(int argc, char *argv[])
{
    MonitorList list;
    return 0;
}

Но снова ругается на
testLibs/monitorlist.cpp:3: undefined reference to `ddcci_probe()'

0
fox4 - 20 Июль, 2016 - 23:01
Изображение пользователя fox4.

Решил потестировать ваш C код
struct monitorlist* dd;
        dd = ddcci_probe();

        while(dd != NULL){
            printf("file: %s (%s)\n", dd->filename, dd->name);
            dd = dd->next;
        }
        ddcci_free_list(dd);

        return 0;

При сборке поймал ошибку
/usr/include/ddccontrol/monitor_db.h:26: ошибка: libxml/xmlstring.h: No such file or directory
что то на ночь глядя ничего умного в голову не пришло хотя похоже проблема тривиальна
если сталкивались то как решили ?

0
nitrofox - 20 Июль, 2016 - 23:33
Изображение пользователя nitrofox.

Я установил библиотеку apt install libxml2-dev
И добавил в pro файл
INCLUDEPATH += /usr/include/libxml2

0
fox4 - 21 Июль, 2016 - 15:42
Изображение пользователя fox4.

Тьфу ты забыл я про INCLUDEPATH спасибо.

0
fox4 - 21 Июль, 2016 - 18:12
Изображение пользователя fox4.

Посмотрел в отладке ddcci_probe() всегда возвращает 0x0 то есть структура не инициализирована и адрес не определён компилятор С это проглатывает поскольку за распределением памяти инициализацией переменных и прочее везде следит программист у С++ более жёсткие ограничения. Я бы посоветовал выкачать все исходники библиотеки не только хедеры и посмотреть реализацию и иерархию вызовов функций. Скорее всего до вызова ddcci_probe() надо сделать кучу подготовительных действий. Возможно в сорцах будет пример использования данной библиотеки.

0
nitrofox - 21 Июль, 2016 - 21:34
Изображение пользователя nitrofox.

Если прогу запустить с под root =) Она вернет список мониторов которыми можно управлять. Вот мой вывод.
file: dev:/dev/i2c-4 (Unknown monitor (VSC3A2C))

Если я правильно понимаю процесс компиляции.. То компилятор С++ прекрасно смог создать объектные файлы. А проблемы появляются на следующем шаге. Линковщик не может найти функцию ddcci_probe()
ls *.o
main.o  monitorlist.o

nm -D /usr/lib/x86_64-linux-gnu/libddccontrol.so.0 | grep ddcci_probe
0000000000004680 T ddcci_probe
00000000000044e0 T ddcci_probe_device


g++ -o MyProgram main.o monitorlist.o -lddccontrol

monitorlist.o: In function `MonitorList::MonitorList()':
monitorlist.cpp:4: undefined reference to `ddcci_probe()'
collect2: error: ld returned 1 exit status

0
fox4 - 21 Июль, 2016 - 21:58
Изображение пользователя fox4.

Ну если исходить из вашей логики то тогда правильней
sudo g++ -o MyProgram main.o monitorlist.o -lddccontrol
у компоновщика должен быть полный доступ к файлам (не совсем догоняю зачем...)
но видимо так надо.

+2
fox4 - 21 Июль, 2016 - 22:39
Изображение пользователя fox4.

Я вспомнил у C++ есть особенность работы с внешними функциями
pListMonitor = ddcci_probe();
надо перенести в обьявления класса (файл monitorlist.h)
#ifndef MONITORLIST_H
#define MONITORLIST_H
extern "C"
{
#include <ddccontrol/ddcci.h>
}
class MonitorList
{
public:

    struct monitorlist* pListMonitor;
    MonitorList(){
        pListMonitor = ddcci_probe();}
};
#endif // MONITORLIST_H

файл (main.cpp)
#include "monitorlist.h"

int main(int argc, char *argv[])
{

    MonitorList List();
        return 0;
}

файл реализации (monitorlist.cpp)
у меня пустой.
Всё прекрасно компилируется.

0
nitrofox - 21 Июль, 2016 - 22:52
Изображение пользователя nitrofox.

Огромное спасибо =)

+2
fox4 - 22 Июль, 2016 - 18:51
Изображение пользователя fox4.

Один момент я тут пообщался с гуру программирования и мне указали на ошибку
когда компилер находит конструкцию
Id1 Id2(...);
то он пытается понять, что это, объявление функции или определение переменной с инициализатором.
если ему не удаётся понять, он делает выбор в сторону функции 0:38:03 SAMT
получается, у тебя в майне не переменная определялась, а объявлялась функция.
конструктор MonitorList нигде не звался, потому компилятор и не искал его в либах 0:39:47 SAMT
вопщем надо разобраться где эта либа лежит и как-то подключить её в .pro

Итак окончательный рабочий вариант
monitorlist.pro

monitorlist.h
monitorlist.cpp
main.cpp
Ещё комментарий от гуру по библиотеке libddccontrol
мдя, негусто
но в целом понятно
используются односвязные списки, их можно оформить как итераторы
указатели на структуры загнать в классы

это так сказать намёк на будущее.

Отправить комментарий

CAPTCHA на основе изображений
Введите цифры