我正在使用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
$
Run Code Online (Sandbox Code Playgroud)
我该如何正确指定库?
我运行下面的命令.它编译和链接但不能正确运行:
$ 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
$
Run Code Online (Sandbox Code Playgroud)
我还缺少什么?
将-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
Run Code Online (Sandbox Code Playgroud)
对于链接,请确保在库(-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
Run Code Online (Sandbox Code Playgroud)
编译器/链接器和运行时系统都需要能够找到共享对象。您可以使用该-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
Run Code Online (Sandbox Code Playgroud)
并非所有系统都支持此选项。如果你的没有,你必须继续前进。
此选项的缺点是您指定的位置嵌入在二进制文件中。如果客户机器上的库不在同一位置,则不会找到该库。因此,某人主目录下的路径仅适用于其计算机上的该用户——不适用于一般人群。OTOH,如果软件默认安装在,例如/opt/packagename/lib,那么指定 with-R可能是合适的。
将目录添加到LD_LIBRARY_PATH环境变量(或其等效项;例如,DYLD_LIBRARY_PATH在 Mac OS X 或SHLIB_PATHHP-UX IIRC 上)。
LD_LIBRARY_PATH=/home/savio/opencv-3.0.0/cmake_binary_dir/lib:$LD_LIBRARY_PATH \
./imagefilter
Run Code Online (Sandbox Code Playgroud)
或者:
export LD_LIBRARY_PATH=/home/savio/opencv-3.0.0/cmake_binary_dir/lib:$LD_LIBRARY_PATH
./imagefilter
Run Code Online (Sandbox Code Playgroud)
第一个符号在程序运行期间设置环境变量。例如,如果您需要比较库的两个版本的行为,它会很有用。第二个符号设置会话的环境变量。您可以将其包含在您的.profile或等效中,以便它适用于每个会话。
有些系统也有LD_RUN_PATH环境变量。并且有些具有环境变量的 32 位和 64 位变体。
这对用户和安装人员来说都是繁琐的;您如何确保为使用您代码的每个人设置了环境变量?然后运行真实程序的环境设置 shell 脚本可以在这里提供帮助。
将该目录添加到配置文件中,该文件指定动态加载程序要搜索的已知目录列表。不用说,这是特定于平台的——文件名、格式、位置(通常在/etc某处)和用于编辑它的机制。该文件可能是/etc/ld.so.conf. 可能有一个程序可以正确编辑配置文件。
将库安装在无论如何都会被搜索的位置(无需重新配置动态加载程序)。这可能是/usr/lib,或者可能是/usr/local/lib其他一些相关目录。
我的 IDE 处理该过程的方式是将 -L 标记放在前面,将 -l 标记放在末尾。所有 -l 标记都需要位于目标之后,以便编译器知道在搜索之前需要解析哪些符号。
gcc -L/path/to/library -o target_here -lfirst -lsecond -lthird ...
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
3021 次 |
| 最近记录: |