听说,没学过OpenGL和vtk就算不上懂得可视化,于是,就赶紧装上一个试一试。
在fedora 12 下
su -c 'yum install vtk-*‘ |
装了许多包,其中vtkdata最大,达到47M,不知道哪个包信赖于它。安装的vtk的版本是vtk-5.4.2-34.fc12.i686
装上之后,就开始写程序,遇到的第一件事就是头文件了。linux下面,vtk的头文件都保存在/usr/include/vtk目录下,因此,头文件前面要加上vtk,比如
编译的第二个程序就出问题了,问题还是出在头文件。
我惊奇地发现,vtk的头文件中居然有错误。
问题出在/usr/include/vtk/vtkstd/string文件中, string中使用了一个头文件
#include "vtkConfigure.h"
|
但是vtkConfigure.h其实是在/usr/include/vtk/目录中,这样,这句话显然应该改成
#include "../vtkConfigure.h"
|
或
这么低级的错误实在不应该犯的。
第二个很严重的问题是,vtk提供的库文件多达200个,对于初学者来说,实在不知道哪个库里面有哪些函数或者某个函数属于哪个库。于是,我搜索咨询冥想之后,想到了一个法子。
cd && mkdir libvtkname
cd /usr/lib
list=`dir libvtk*`
for i in $list; do nm -D $i|c++filt > ~/libvtkname/$i.name; done |
这几句话的意思是,将vtk所有库文件中的符号写到~/libvtkname/这个目录中去,每个库文件对应一个符号文件。其中的核心是nm -D命令和c++filt命令。前者打印出动态符号,和objdump -T功能一样,但是这个动态符号中标记太多不符合人类阅读习惯,而c++filt刚好就是这样一个配套工具,它将这个符号解析成符合阅读习惯的函数形式。
这样,只要再遇到undefined reference, 我就可心直接去这些符号文件中进行搜索,而不用再一个个试那些库文件了。
比如我在刚才建好的libvtkname目录中找vtkActor::New()这样一个符号
它就会给出一堆匹配结果
libvtkGeovis.so.5.4.2.name: U vtkActor::New() libvtkGeovis.so.5.4.name: U vtkActor::New() libvtkGeovis.so.name: U vtkActor::New() libvtkHybrid.so.5.4.2.name: U vtkActor::New() libvtkHybrid.so.5.4.name: U vtkActor::New() libvtkHybrid.so.name: U vtkActor::New() libvtkInfovis.so.5.4.2.name: U vtkActor::New() libvtkInfovis.so.5.4.name: U vtkActor::New() libvtkInfovis.so.name: U vtkActor::New() libvtkRenderingJava.so.5.4.2.name: U vtkActor::New() libvtkRenderingJava.so.5.4.name: U vtkActor::New() libvtkRenderingJava.so.name: U vtkActor::New() libvtkRenderingPythonD.so.5.4.2.name: U vtkActor::New() libvtkRenderingPythonD.so.5.4.name: U vtkActor::New() libvtkRenderingPythonD.so.name: U vtkActor::New() libvtkRendering.so.5.4.2.name:049a3960 T vtkActor::New() libvtkRendering.so.5.4.name:049a3960 T vtkActor::New() libvtkRendering.so.name:049a3960 T vtkActor::New() libvtkRenderingTCL.so.5.4.2.name: U vtkActor::New() libvtkRenderingTCL.so.5.4.name: U vtkActor::New() libvtkRenderingTCL.so.name: U vtkActor::New() libvtkViews.so.5.4.2.name: U vtkActor::New() libvtkViews.so.5.4.name: U vtkActor::New() libvtkViews.so.name: U vtkActor::New() libvtkWidgets.so.5.4.2.name: U vtkActor::New() libvtkWidgets.so.5.4.name: U vtkActor::New() libvtkWidgets.so.name: U vtkActor::New() |
这些匹配结果分两类,一类前面有T标记,一类前面有U标记,而U标记明显要更多一些,由此判断,T应该是表示定义,而U表示使用。但为什么T也会出现多次呢,那是因为同一个库文件可能有多个版本,或者有多个链接。这样,我就找到了vtkActor::New()这个符号在libvtkRendering这个库中。
幸运的是,我发现libvtkRendering这个库中函数还蛮多,加了这一个库就把我第二个程序给搞定了。
补充一下,nm和objdump -t是一样的,而nm -D和objdump -T是一样的,前者打印的实际上是用于调试用的符号,即gcc加上-g选项才会有,而后者是专用于动态链接库的,即只要是动态链接库就必须要有的那些符号。
阅读(8968) | 评论(2) | 转发(0) |