我正在使用OpenCV调用编写程序,我想编译它并生成可执行文件。 我已经阅读了gcc教程,但我仍然想知道如何链接我正在使用的OpenCV库。 我的命令和相关输出如下:
$ gcc -I/home/savio/opencv-3.0.0/include/opencv -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
> -lopencv_core -lopencv_highgui -lopencv_imgproc imagefilter.c -o imagefilter
/tmp/ccDUEgAk.o: nella funzione "cvDecRefData":
imagefilter.c:(.text+0xa6a): riferimento non definito a "cvFree_"
imagefilter.c:(.text+0xaf2): riferimento non definito a "cvFree_"
/tmp/ccDUEgAk.o: nella funzione "cvGetRow":
imagefilter.c:(.text+0xc08): riferimento non definito a "cvGetRows"
/tmp/ccDUEgAk.o: nella funzione "cvGetCol":
imagefilter.c:(.text+0xc36): riferimento non definito a "cvGetCols"
/tmp/ccDUEgAk.o: nella funzione "cvReleaseMatND":
imagefilter.c:(.text+0xc50): riferimento non definito a "cvReleaseMat"
/tmp/ccDUEgAk.o: nella funzione "cvSubS":
imagefilter.c:(.text+0xdac): riferimento non definito a "cvAddS"
/tmp/ccDUEgAk.o: nella funzione "cvCloneSeq":
imagefilter.c:(.text+0xde5): riferimento non definito a "cvSeqSlice"
/tmp/ccDUEgAk.o: nella funzione "cvSetNew":
imagefilter.c:(.text+0xe52): riferimento non definito a "cvSetAdd"
/tmp/ccDUEgAk.o: nella funzione "cvGetSetElem":
imagefilter.c:(.text+0xefa): riferimento non definito a "cvGetSeqElem"
/tmp/ccDUEgAk.o: nella funzione "cvReadIntByName":
imagefilter.c:(.text+0xfa9): riferimento non definito a "cvGetFileNodeByName"
/tmp/ccDUEgAk.o: nella funzione "cvReadRealByName":
imagefilter.c:(.text+0x1053): riferimento non definito a "cvGetFileNodeByName"
/tmp/ccDUEgAk.o: nella funzione "cvReadStringByName":
imagefilter.c:(.text+0x10e6): riferimento non definito a "cvGetFileNodeByName"
/tmp/ccDUEgAk.o: nella funzione "cvReadByName":
imagefilter.c:(.text+0x1126): riferimento non definito a "cvGetFileNodeByName"
imagefilter.c:(.text+0x113c): riferimento non definito a "cvRead"
/tmp/ccDUEgAk.o: nella funzione "cvContourPerimeter":
imagefilter.c:(.text+0x1170): riferimento non definito a "cvArcLength"
/tmp/ccDUEgAk.o: nella funzione "cvCalcHist":
imagefilter.c:(.text+0x11b2): riferimento non definito a "cvCalcArrHist"
/tmp/ccDUEgAk.o: nella funzione "cvEllipseBox":
imagefilter.c:(.text+0x127e): riferimento non definito a "cvEllipse"
/tmp/ccDUEgAk.o: nella funzione "cvFont":
imagefilter.c:(.text+0x12c8): riferimento non definito a "cvInitFont"
/tmp/ccDUEgAk.o: nella funzione "main":
imagefilter.c:(.text+0x1396): riferimento non definito a "cvLoadImage"
imagefilter.c:(.text+0x13af): riferimento non definito a "cvGetSize"
imagefilter.c:(.text+0x13c1): riferimento non definito a "cvCreateImage"
imagefilter.c:(.text+0x13ed): riferimento non definito a "cvSmooth"
imagefilter.c:(.text+0x1403): riferimento non definito a "cvSaveImage"
imagefilter.c:(.text+0x141b): riferimento non definito a "cvReleaseImage"
imagefilter.c:(.text+0x1427): riferimento non definito a "cvReleaseImage"
collect2: error: ld returned 1 exit status
$
我应该如何正确指定库?
我在下面运行了命令。它编译和链接但运行不正确:
$ gcc imagefilter.c -o imagefilter -I/home/savio/opencv-3.0.0/include/opencv \
> -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
> -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_core
$ ./imagefilter lena_noise.BMP
./imagefilter: error while loading shared libraries: libopencv_imgcodecs.so.3.0: cannot open shared object file: No such file or directory
$
我还缺少什么?
答案 0 :(得分:6)
将-L和-l移动到命令行的末尾:
gcc imagefilter.c -o imagefilter -I/home/savio/opencv-3.0.0/include/opencv -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib -lopencv_core -lopencv_highgui -lopencv_imgproc
答案 1 :(得分:1)
我的IDE处理进程的方法是将-L标记放在前面,将-l标记放在最后。所有-l标记都需要在目标之后,以便编译器在搜索之前知道需要解析哪些符号。
gcc -L/path/to/library -o target_here -lfirst -lsecond -lthird ...
答案 2 :(得分:0)
对于链接,请确保在库(-lxxx
选项)之前指定目标文件(或源文件)。并确保给定库的-L
选项出现在使用它的-l
选项之前。图书馆的顺序很重要;按顺序列出库,以便库列出之前列出的参考代码。 (在设计库集时,避免库之间的循环引用;它们是瘟疫。)
$ gcc imagefilter.c -o imagefilter -I/home/savio/opencv-3.0.0/include/opencv \
> -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
> -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_core
编译器/链接器和运行时系统都需要能够找到共享对象。您可以使用-L
选项告诉链接器在哪里找到库。您可以通过多种方式告知运行时(动态加载器)在何处查找库:
在某些系统上,您可以在命令行中添加-R
选项,以指定在运行时可以找到库的位置:
$ gcc imagefilter.c -o imagefilter -I/home/savio/opencv-3.0.0/include/opencv \
> -L/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
> -R/home/savio/opencv-3.0.0/cmake_binary_dir/lib \
> -lopencv_imgcodecs -lopencv_imgproc -lopencv_highgui -lopencv_core
并非所有系统都支持此选项。如果你没有,你必须继续前进。
此选项的缺点是您指定的位置嵌入在二进制文件中。如果客户机器上的库不在同一位置,则找不到库。因此,某人主目录下的路径仅适用于其计算机上的该用户 - 而不适用于一般人群。 OTOH,如果软件默认安装在/opt/packagename/lib
中,那么使用-R
指定该软件可能是合适的。
将目录添加到LD_LIBRARY_PATH
环境变量(或其等效项;例如,在Mac OS X上为DYLD_LIBRARY_PATH
,或在HP-UX IIRC上为SHLIB_PATH
。
LD_LIBRARY_PATH=/home/savio/opencv-3.0.0/cmake_binary_dir/lib:$LD_LIBRARY_PATH \
./imagefilter
或:
export LD_LIBRARY_PATH=/home/savio/opencv-3.0.0/cmake_binary_dir/lib:$LD_LIBRARY_PATH
./imagefilter
只要程序正在运行,第一个表示法就会设置环境变量。例如,如果您需要比较库的两个版本的行为,它会很有用。第二种表示法为会话设置环境变量。您可以在.profile
或同等内容中包含该内容,以便适用于每个会话。
某些系统也有LD_RUN_PATH
环境变量。有些环境变量有32位和64位变体。
这对于用户和安装人员来说都很繁琐;您如何确保为使用您的代码的每个人设置环境变量?然后运行真实程序的环境设置shell脚本可以在这里提供帮助。
将目录添加到配置文件中,该文件指定要搜索的动态加载程序的已知目录列表。毋庸置疑,这是特定于平台的 - 文件名,格式,位置(通常在/etc
某处)和用于编辑它的机制。该文件可能是/etc/ld.so.conf
。可能有一个程序正确编辑配置文件。
将库安装在将要搜索的位置(无需重新配置动态加载程序)。这可能是/usr/lib
,也可能是/usr/local/lib
或其他相关目录。