Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Magnolia от Март 21, 2012, 12:47



Название: вопрос по линковке
Отправлено: Magnolia от Март 21, 2012, 12:47
Всем привет! Стоит такая задача: есть проект на С++ под Qt, к нему нужно прилинковать объектный файл (откомпилированный исходник на С). Работаю в Qt Creator. Подскажите как в Creator'e либо в консоли собрать проект вместе с добавленным объектником (или же в проект добавлять сам исходник, а не готовый объектный файл). Нужно MakeFile править или что-то другое? 


Название: Re: вопрос по линковке
Отправлено: kambala от Март 21, 2012, 13:55
если есть исходник, то добавить его в проект можно, если нажать правой кнопкой мыши на папку в дереве файлов - добавить существующий, или просто дописать относительный путь к исходнику в соответствующий раздел файла .pro и сохранить его


Название: Re: вопрос по линковке
Отправлено: FricGeger от Март 21, 2012, 14:06
Есть несколько вариантов:

-добавить сам файл в исходники. Для добавить в файл проекта (*.pro) в разделе SOURCES ваш файл.

-скомпилировать дополнительные классы/функции в статическую библиотеку. Для этого в файл проекта нужно добавить путь до исходников(раздел INCLUDEPATH), чтобы проект мог найти требуемые header. Еще потребуется указать путь до статической библиотеки(LIBS), в которой находится реализации требуемых функций.


Я бы воспользовался вторым вариантом, хотя все зависит от конкретной задачи.

Make file создаст qmake по вашему pro файлу. make file править не надо.


Название: Re: вопрос по линковке
Отправлено: Magnolia от Март 21, 2012, 14:08
я так и делала, но при сборке проекта посыпались ошибки:

qtcpportlist.o: In function `QTcpPortList::timerEvent(QTimerEvent*)':
/home/Multiplexor_v2.5/qtcpportlist.cpp:60: undefined reference to `wdog_proc()'
collect2: выполнение ld завершилось с кодом возврата 1
make: Выход из каталога `/home/Multiplexor_v2.5'
make: *** [multiplexorConsole] Ошибка 1
Процесс «/usr/bin/make» завершился с кодом 2.
Возникла ошибка при сборке проекта multiplexorConsole (цель: Desktop)
Во время выполнения сборки на этапе «Сборка»

Процедура wdog_proc() находится как раз в исходнике, который я добавляю к проекту. В qtcpportlist.cpp я объявила ее как
Код:
extern void wdog_proc();
. Ругается на строчку, где я вызываю эту процедуру, делаю это как обычно
Код:
wdog_proc();
. Что я делаю неправильно?


Название: Re: вопрос по линковке
Отправлено: Magnolia от Март 21, 2012, 14:10
Воспользовалась первым методом - просто добавила файл в исходники.


Название: Re: вопрос по линковке
Отправлено: FricGeger от Март 21, 2012, 14:27
Я надеюсь что вы добавили исходный файл, а не объектный.


Название: Re: вопрос по линковке
Отправлено: Magnolia от Март 21, 2012, 15:02
Да, исходный. Но сборка завершается с ошибками,  о которых писала выше.


Название: Re: вопрос по линковке
Отправлено: FricGeger от Март 21, 2012, 15:04
Приложите исходные файлы, того где используете функцию и того где она описана


Название: Re: вопрос по линковке
Отправлено: Magnolia от Март 21, 2012, 15:20
qtcpportlist.cpp (там где вызывается функция):
Код:
#include "qtcpportlist.h"
#include "QFile"
extern void wdog_proc();

// глобальная переменная для чтения конфигурации
static QFile* cfgFile = NULL;
//static QFile* shadow_file = NULL;

#define DEFAULT_CONFIG_TEMPLATE    "config.csv"

// функции класса списка всех портов в памяти

////////////////////////////////////////////////////////////////////////////////
// конструктор
////////////////////////////////////////////////////////////////////////////////
QTcpPortList::QTcpPortList(QObject *parent,bool flag_wdog) :
        QObject(parent)
{
    // инициализация таймера, для проверки списка портов
    m_iTimerID = startTimer(PORTLIST_TIMER_INTERVAL);   
    flag_file = false;
    flag_msg_nofile = false;
    flag_msg_empty = false;
    wdog_timer = 0;
    wdog = flag_wdog;

}

////////////////////////////////////////////////////////////////////////////////
// деструктор
////////////////////////////////////////////////////////////////////////////////
QTcpPortList::~QTcpPortList()
{
    // закрываем конфигурационный файл, если он был открыт
    if (cfgFile)
    {
        cfgFile->close();
        delete cfgFile;
        cfgFile = NULL;
    }
}

////////////////////////////////////////////////////////////////////////////////
// Обработчик событий таймера
////////////////////////////////////////////////////////////////////////////////
void QTcpPortList::timerEvent(QTimerEvent *event)
{

    // проверяем, что событие от нужного таймера Порт
    if ( event->timerId() == m_iTimerID )
    {
        //вызов процедуры wdog_proc раз в 10 сек
        if (wdog)
            if (wdog_timer<10)
            {
                 wdog_timer++;
            }
            else
            {
                wdog_proc();
                wdog_timer = 0;
            }
...

wdproc.c (там где функция описана)
Код:
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <termios.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include <string.h>
#include <time.h>

typedef uint8_t byte;
typedef uint16_t word;
typedef int16_t sword;
typedef uint32_t dword;
typedef int32_t sdword;
typedef uint64_t qword;
typedef int64_t sqword;
typedef double   dbl;

#pragma pack(1)

typedef struct {
  word          len;
  word          task;
  dword         pid;
  dword         ip;
  word          port;
  word          flags;
  word          devs;
  word          func;
  } s_wdpoll;

#pragma pack()

s_wdpoll        wd_pack= {sizeof(s_wdpoll), 2, 0, 0, 0, 0, 0, 0};
int             wd_fd;
fd_set          wd_fdset;

extern dword    wdog_port;

//*****************************************************   init_c127
static int init_c127(int port, int *pfd, int stream) {
struct sockaddr_in s_sock;

if (*pfd > 0)  close(*pfd);
s_sock.sin_family = AF_INET;
s_sock.sin_port = htons(port);
s_sock.sin_addr.s_addr= htonl(0x7f000001);
if ((*pfd= socket(PF_INET, stream, 0)) < 0)  { *pfd=0;  return -1; }
if (connect(*pfd, (struct sockaddr *)&s_sock, sizeof((s_sock))) < 0)
  { close(*pfd);  *pfd=0;  return -3; }
return 0;
}


//*****************************************************   wdog_proc
void wdog_proc()  {
struct timeval tout;
static char buf[128];

if (!wd_fd)  {
  if (!wdog_port)  return;
  if (init_c127(wdog_port, &wd_fd, SOCK_STREAM))  { wd_fd= 0;  return; }
  wd_pack.pid= getpid();
  FD_ZERO(&wd_fdset);
  }
tout.tv_usec= tout.tv_sec= 0;
FD_SET(wd_fd, &wd_fdset);
while (select(FD_SETSIZE, &wd_fdset, 0, 0, &tout) > 0)
  if (read(wd_fd, buf, sizeof(buf)) <= 0)  { close(wd_fd); wd_fd= 0; return; }
if (write(wd_fd, &wd_pack, wd_pack.len) != wd_pack.len) { close(wd_fd); wd_fd= 0; return;}
}


Название: Re: вопрос по линковке
Отправлено: kambala от Март 21, 2012, 15:30
не уверен, но возможно объявление функции в qtcpportlist.cpp надо заключить в
Код
C++ (Qt)
extern "C" {
   extern void wdog_proc();
}


Название: Re: вопрос по линковке
Отправлено: Magnolia от Март 21, 2012, 15:49
спасибо большое, заработало!