C语言 对 *.h 文件中声明的函数的未定义引用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7433984/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:38:47  来源:igfitidea点击:

undefined reference to function declared in *.h file

creferenceundefined

提问by ulyssis

I am a unskilled programmer and new to linux, I run into a problem when complining. I have two files 'ex_addinst.c' and 'lindo.h' in the same folder, I input command :

我是一个不熟练的程序员,并且是 linux 的新手,我在编译时遇到了问题。我在同一个文件夹中有两个文件“ex_addinst.c”和“lindo.h”,我输入命令:

g++ -c ex_addinst.c

then, a object file ex_addinst.o is genetated with a warning:

然后,生成一个带有警告的目标文件 ex_addinst.o:

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

then I leak them with

然后我泄漏它们

g++ -Wall -o ex_addinst ex_addinst.o

and get the following info:

并获得以下信息:

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

I guess that the header file 'lindo.h' is not complied into the .o file, but I have no idea what to do now. I have tried gcc, but get the same error. the version of my g++ and gcc is 4.4.5. I am using Ubuntu 10.10.

我猜头文件 'lindo.h' 没有被编译到 .o 文件中,但我现在不知道该怎么做。我试过 gcc,但得到同样的错误。我的 g++ 和 gcc 的版本是 4.4.5。我正在使用 Ubuntu 10.10。

All the functions and structures have been declared in 'lindo.h'.

所有的函数和结构都在“lindo.h”中声明。

part of ex_addinst.c is as follows:

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();
}

part of 'lindo.h' is:

'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);

Thank you!

谢谢!



Thank you guys answering my problem. As you suggested, I need to link the library when complining. I have gotten the executable file with:

谢谢各位解答我的问题。正如您所建议的,我需要在编译时链接库。我已经得到了可执行文件:

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

but there comes another problem when run the executable file ex_addinst: after run:

但是在运行可执行文件ex_addinst时出现了另一个问题:运行后:

./ex_addinst

there comes:

来了:

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

The tricky thing is, liblindo64.so.6.0is in the lib folder which contains:

棘手的是,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

I have created symbolic links between liblindo64.so.6.0and liblindo64.sowith

我创建之间的符号链接liblindo64.so.6.0liblindo64.so

ln -sf liblindo64.so.6.0 liblindo64.so

but it doesn't help.

但它没有帮助。

Can anyone tell me what is wrong here?

谁能告诉我这里有什么问题?

(I am not sure I should put this question in a new post, but I think currently it is better to follow the old one)

(我不确定我是否应该在新帖子中提出这个问题,但我认为目前最好遵循旧的问题)

回答by Praetorian

Ok, lindo.hcontains the prototypes for those functions, but where are the functions actually defined? If they're in another C file you need to compile that one too, and link both the object files together.

好的,lindo.h包含这些函数的原型,但函数实际定义在哪里?如果它们在另一个 C 文件中,您也需要编译该文件,并将两个目标文件链接在一起。

If the functions are part of another static library, you need to tell the linker to link that library along with your object file.

如果函数是另一个静态库的一部分,您需要告诉链接器将该库与您的目标文件一起链接。

If they're defined with a shared library, you can probably get g++ to still link to it at compile time, and take care of the library loading etc. Otherwise you'll need to load the library at runtime and reference the functions from the library. This Wikipedia article on dynamic loadingof shared libraries contains some example code.

如果它们是用共享库定义的,您可能可以让 g++ 在编译时仍然链接到它,并负责库加载等。否则您需要在运行时加载库并从图书馆。这篇关于动态加载共享库的维基百科文章包含一些示例代码。

回答by Pete Wilson

Try

尝试

g++ -Wall -o ex_addinst ex_addinst.c

g++ -Wall -o ex_addinst ex_addinst. C

instead of

代替

g++ -Wall -o ex_addinst ex_addinst.o

g++ -Wall -o ex_addinst ex_addinst.o

You want to compile the .c file, not the .o file.

您要编译 .c 文件,而不是 .o 文件。

回答by psycho

undefined reference to ...is not a declaration problem. The compiler fails because it can't find symbols (objects) which are related to those declared functions.
In your case, you use the Limbo API, and include the header file, but you don't tell the compiler to link with the library : that's why it doesn't find symbols.
EDIT: I had forgotten the part when you say you're new to Linux. To link with the library, you need to use the -L/-loptions of g++. man g++is always a good read, and the Limbo's documentation should be, too.

undefined reference to ...不是声明问题。编译器失败是因为它找不到与那些声明的函数相关的符号(对象)。
在您的情况下,您使用 Limbo API,并包含头文件,但您没有告诉编译器与库链接:这就是它找不到符号的原因。
编辑:当您说您是 Linux 新手时,我忘记了这部分内容。要与库链接,您需要使用g++的-L/-l选项。man g++总是很好读,Limbo 的文档也应该如此。

回答by Dmitri

You need to tell gcc to link with the library or object file(s) that contain the LS... functions you're using. The header file tells the compiler how to call them, but the linker needs to know where to get the compiled code from.

您需要告诉 gcc 链接到包含您正在使用的 LS... 函数的库或目标文件。头文件告诉编译器如何调用它们,但链接器需要知道从哪里获取编译后的代码。