web-dev-qa-db-ja.com

* .hファイルで宣言された関数への未定義の参照

私は熟練していないプログラマーであり、Linuxを初めて使用するため、コンパイル時に問題が発生します。同じフォルダに2つのファイル「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です。 Ubuntu10.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.は次のものを含む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.liblindo64.soの間にシンボリックリンクを作成しました

ln -sf liblindo64.so.6.0 liblindo64.so

しかし、それは役に立ちません。

ここで何が悪いのか誰か教えてもらえますか?

(この質問を新しい投稿に入れるべきかどうかはわかりませんが、現在は古い質問に従う方が良いと思います)

6
ulyssis

OK、 lindo.hにはこれらの関数のプロトタイプが含まれていますが、関数は実際にどこで定義されていますか?それらが別のCファイルにある場合は、それもコンパイルし、両方のオブジェクトファイルをリンクする必要があります。

関数が別の静的ライブラリの一部である場合は、そのライブラリをオブジェクトファイルと一緒にリンクするようにリンカに指示する必要があります。

共有ライブラリで定義されている場合は、コンパイル時にg ++にリンクさせて、ライブラリの読み込みなどを処理できます。それ以外の場合は、実行時にライブラリを読み込み、から関数を参照する必要があります。図書館。共有ライブラリの 動的読み込み に関するこのウィキペディアの記事には、いくつかのサンプルコードが含まれています。

15
Praetorian

試してみてください

g ++ -Wall -o ex_addinst ex_addinst .c

の代わりに

g ++ -Wall -o ex_addinst ex_addinst.o

.oファイルではなく.cファイルをコンパイルする必要があります。

1
Pete Wilson

undefined reference to ...は宣言の問題ではありません。宣言された関数に関連するシンボル(オブジェクト)が見つからないため、コンパイラーは失敗します。
あなたの場合、Limbo APIを使用し、ヘッダーファイルをインクルードしますが、コンパイラーにライブラリーとリンクするように指示しません。そのため、シンボルが見つかりません。
[〜#〜] edit [〜#〜]:Linuxを初めて使用する場合、その部分を忘れていました。ライブラリとリンクするには、g ++の-L/-lオプションを使用する必要があります。 man g++は常に良い読み物であり、Limboのドキュメントも読む必要があります。

1
psycho

使用しているLS ...関数を含むライブラリまたはオブジェクトファイルにリンクするようにgccに指示する必要があります。ヘッダーファイルはコンパイラーにそれらを呼び出す方法を指示しますが、リンカはコンパイルされたコードをどこから取得するかを知る必要があります。

1
Dmitri