Неопределенная ссылка на функцию, объявленную в файле *.h

Я неквалифицированный программист и новичок в Linux, я сталкиваюсь с проблемой при компиляции. У меня есть два файла ex_addinst.c и lindo.h в одной папке, я ввожу команду:

g++ -c ex_addinst.c

Затем объектный файл ex_addinst.o генерируется с предупреждением:

ex_addinst.c: In function ‘int main()’:
ex_addinst.c:80: warning: deprecated conversion from string constant to ‘char*’

тогда я сливаю их

g++ -Wall -o ex_addinst ex_addinst.o

и получите следующую информацию:

ex_addinst.o: In function `main':
ex_addinst.c:(.text+0x2b): undefined reference to `LSloadLicenseString'
ex_addinst.c:(.text+0x75): undefined reference to `LSgetVersionInfo'
ex_addinst.c:(.text+0xae): undefined reference to `LScreateEnv'
ex_addinst.c:(.text+0x10a): undefined reference to `LSgetErrorMessage'
...
...
ex_addinst.c:(.text+0x1163): undefined reference to `LSdeleteEnv'
collect2: ld returned 1 exit status

Я предполагаю, что заголовочный файл 'lindo.h' не соответствует.o файлу, но я понятия не имею, что делать сейчас. Я пробовал gcc, но получаю ту же ошибку. версия моего g++ и gcc - 4.4.5. Я использую Ubuntu 10.10.

Все функции и структуры были объявлены в 'lindo.h'.

часть ex_addinst.c выглядит следующим образом:

    #include <stdio.h>
    #include <stdlib.h>
    /* LINDO API header file */
    #include "lindo.h"
        enter code here
int CALLTYPE LSwriteMPIFile(pLSmodel pModel,
                             char     *pszFname);


/* Define a macro to declare variables for
    error checking */
#define APIERRORSETUP  \
   int nErrorCode; \
   char cErrorMessage[LS_MAX_ERROR_MESSAGE_LENGTH] \
/* Define a macro to do our error checking */
#define APIERRORCHECK  \
   if (nErrorCode) \
   { \
      if ( pEnv) \
      { \
         LSgetErrorMessage( pEnv, nErrorCode, \
          cErrorMessage); \
         printf("nErrorCode=%d:  %s\n", nErrorCode, \
          cErrorMessage); \
      } else {\
         printf( "Fatal Error\n"); \
      } \
      exit(1); \
   } \

#define APIVERSION \
{\
    char szVersion[255], szBuild[255];\
    LSgetVersionInfo(szVersion,szBuild);\
    printf("\nLINDO API Version %s built on %s\n",szVersion,szBuild);\
}\
/* main entry point */
int main()
{
   APIERRORSETUP;
   pLSenv pEnv;
   pLSmodel pModel;
   char MY_LICENSE_KEY[1024];

 /*****************************************************************
  * Step 1: Create a model in the environment.
  *****************************************************************/
   nErrorCode = LSloadLicenseString("home/li/work/tools/lindo/lindoapi/license/lndapi60.lic", MY_LICENSE_KEY);
   if ( nErrorCode != LSERR_NO_ERROR)
   {
      printf( "Failed to load license key (error %d)\n",nErrorCode);
      exit( 1);
   }
......
......
......
   APIERRORCHECK;
   {
      int nStatus;
      double objval=0.0, primal[100];
      /* Get the optimization result */
      nErrorCode = LSgetInfo(pModel, LS_DINFO_GOP_OBJ, &objval);
      APIERRORCHECK;
      LSgetMIPPrimalSolution( pModel, primal) ;
      APIERRORCHECK;
      printf("\n\nObjective = %f \n",objval);
      printf("x[0] = %f \n",primal[0]);
      printf("x[1] = %f \n",primal[1]);
      /* Get the linearity of the solved model */
      nErrorCode = LSgetInfo (pModel, LS_IINFO_GOP_STATUS, &nStatus);
      APIERRORCHECK;
      /* Report the status of solution */
      if (nStatus==LS_STATUS_OPTIMAL || nStatus==LS_STATUS_BASIC_OPTIMAL)
      printf("\nSolution Status: Globally Optimal\n");
      else if (nStatus==LS_STATUS_LOCAL_OPTIMAL)
      printf("\nSolution Status: Locally Optimal\n\n");
      else if (nStatus==LS_STATUS_INFEASIBLE)
      printf("\nSolution Status: Infeasible\n\n");
   }

 /* >>> Step 7 <<< Delete the LINDO environment */
   LSdeleteEnv(&pEnv);

  /* Wait until user presses the Enter key */
   printf("Press <Enter> ...");
   getchar();
}

часть 'lindo.h' это:

/*********************************************************************
 * Structure Creation and Deletion Routines (4)                      *
 *********************************************************************/

 pLSenv CALLTYPE LScreateEnv(int     *pnErrorcode,
                             char    *pszPassword);

 pLSmodel CALLTYPE LScreateModel(pLSenv pEnv,
                             int     *pnErrorcode);

 int CALLTYPE LSdeleteEnv(pLSenv *pEnv);


 int CALLTYPE LSdeleteModel(pLSmodel *pModel);


 int CALLTYPE LSloadLicenseString(char *pszFname, char *pachLicense);

 void CALLTYPE LSgetVersionInfo(char *pachVernum, char    *pachBuildDate);

Спасибо!


Спасибо, ребята, отвечая на мою проблему. Как вы предложили, мне нужно связать библиотеку при компиляции. Я получил исполняемый файл с:

gcc -o ex_addinst  ./ex_addinst.o -L/home/li/work/tools/lindo/lindoapi/bin/linux64 -m64 -llindo64  -lmosek64 -lconsub3 -lc -ldl -lm -lguide -lpthread -lsvml -limf -lirc

но возникает другая проблема при запуске исполняемого файла ex_addinst: после запуска:

./ex_addinst

там приходит:

./ex_addinst: error while loading shared libraries: liblindo64.so.6.0: cannot open shared object file: No such file or directory

Хитрость в том, что liblindo64.so.6.0 находится в папке lib, которая содержит:

libconsub3.so  libirc.so          liblindojni.so        libmosek64.so.5.0  lindo.par
libguide.so    liblindo64.so      liblindojni.so.6.0.3  libsvml.so         placeholder
libimf.so      liblindo64.so.6.0  libmosek64.so         lindoapivars.sh    runlindo

Я создал символические ссылки между liblindo64.so.6.0 и liblindo64.so с

ln -sf liblindo64.so.6.0 liblindo64.so

но это не помогает

Может кто-нибудь сказать мне, что здесь не так?

(Я не уверен, что должен поставить этот вопрос в новом посте, но я думаю, что в настоящее время лучше следовать старому)

5 ответов

В порядке, lindo.h содержит прототипы для этих функций, но где эти функции на самом деле определены? Если они находятся в другом C-файле, вам нужно скомпилировать его и связать оба объектных файла вместе.

Если функции являются частью другой статической библиотеки, вы должны указать компоновщику связать эту библиотеку вместе с вашим объектным файлом.

Если они определены с разделяемой библиотекой, вы, вероятно, можете заставить g++ по-прежнему ссылаться на нее во время компиляции, и позаботиться о загрузке библиотеки и т. Д. В противном случае вам нужно будет загрузить библиотеку во время выполнения и ссылаться на функции из библиотека. Эта статья в Википедии о динамической загрузке разделяемых библиотек содержит пример кода.

Вы должны указать gcc ссылку на библиотеку или объектный файл (ы), которые содержат функции LS..., которые вы используете. Заголовочный файл сообщает компилятору, как их вызывать, но компоновщик должен знать, откуда взять скомпилированный код.

Пытаться

g++ -Wall -o ex_addinst ex_addinst.с

вместо

g++ -Wall -o ex_addinst ex_addinst.o

Вы хотите скомпилировать файл.c, а не файл.o.

undefined reference to ... это не проблема объявления. Компилятор не работает, потому что он не может найти символы (объекты), которые связаны с этими объявленными функциями.
В вашем случае вы используете Limbo API и включаете заголовочный файл, но не говорите компилятору связываться с библиотекой: поэтому он не находит символы.
РЕДАКТИРОВАТЬ: я забыл часть, когда вы говорите, что вы новичок в Linux. Для связи с библиотекой вам необходимо использовать -L/-l варианты g++. man g++ всегда хорошо читается, и документация Limbo тоже должна быть.

Для записи и добавления файлов заголовков:

Заголовочный файл

      //arithmatic.h
#ifndef _ARITHMATIC_H
#define _ARITHMATIC_H

int two_num_sum(int x, int y);

#endif
      //arithmatic.c
#include "arithmatic.h"

int two_num_sum(int x, int y){
 return x +y;
}

Основной файл:

      #include<stdio.h>
#include "arithmatic.h"

int main(){
 int sum = two_num_sum(3, 4);
  
  printf("%d",sum);

 return 0

Для компиляции: вам нужно скомпилироватьarithmatic.cфайл тоже.

      $ gcc arithmatic.c main.c -o sum_program
$./sum_program
Другие вопросы по тегам