OpenVolumeMesh编译的一些错误解决

来源:互联网 发布:学舞蹈的干着爽 知乎 编辑:程序博客网 时间:2024/06/05 17:58

OpenVolumeMesh编译的一些错误解决

预备

首先去官网下载源代码:http://www.openvolumemesh.org/download/

文件:openvolumemesh-src-1.1.0.tar.gz

之后安装通常的Cmake操作生成相应的工程文件,我这里生成的是VS 2013 (Update 2)的工程。

错误说明

不修改源码直接编译上述生成的工程,最终可以得到OpenVolumeMesh.lib文件(DebugRelease版本的都可以得到,在Cmake时候配置生成两个版本即可)。之后使用下面例子测试该库,具体代码如下:

[cpp] view plaincopyprint?
  1. #include <OpenVolumeMesh\FileManager\FileManager.hh>  
  2. #include <iostream>  
  3. #include <string>  
  4. #include <OpenVolumeMesh/Geometry/VectorT.hh>  
  5. // Hexahedral meshes  
  6. #include <OpenVolumeMesh/Mesh/HexahedralMesh.hh>  
  7. // Polyhedral meshes  
  8. #include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>  
  9. using namespace std;  
  10. using namespace OpenVolumeMesh;  
  11. int main()  
  12. {  
  13.     OpenVolumeMesh::GeometricPolyhedralMeshV3f myMesh;  
  14.     const string s = "test.poly";  
  15.     OpenVolumeMesh::IO::FileManager fm;   
  16.     std::cout << fm.readFile(s, myMesh) << std::endl;  
  17.     return 0;  
  18. }  


 

VS工程中配置好相应的库文件和头文件之后,直接编译,会提示如下链接错误(

[cpp] view plaincopyprint?
  1. OpenVolumeMesh::IO::FileManager::readFile  
)

[cpp] view plaincopyprint?
  1. 1>main.obj : error LNK2001: 无法解析的外部符号 "public: bool __thiscall OpenVolumeMesh::IO::FileManager::readFile<class OpenVolumeMesh::GeometryKernel<class OpenVolumeMesh::Geometry::VectorT<float,3>,class OpenVolumeMesh::TopologyKernel> >(class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,class OpenVolumeMesh::GeometryKernel<class OpenVolumeMesh::Geometry::VectorT<float,3>,class OpenVolumeMesh::TopologyKernel> &,bool,bool)const " (??$readFile@V?$GeometryKernel@V?$VectorT@M$02@Geometry@OpenVolumeMesh@@VTopologyKernel@3@@OpenVolumeMesh@@@FileManager@IO@OpenVolumeMesh@@QBE_NABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAV?$GeometryKernel@V?$VectorT@M$02@Geometry@OpenVolumeMesh@@VTopologyKernel@3@@2@_N2@Z)  


问题解决过程

很长的错误,但是很明显的就是说readFile这个函数不匹配或者未定义,通常情况下这种错误的原因有以下几种:

1.       DebugRelease版本的库混用

2.       X86x64的库混用

3.       编译库的编译器版本不同,比如说VS2010编译出的库一般情况是不能用在VS2013

4.       这个函数仅仅在头文件中声明,但是编译时候没有链接到lib中(这个错误原因属于此)

之后安排排查上述各种错误,最终可以发现前三个没有任何问题,整个编译过程中一直用的同一个环境,没有任何更改。所以应该是最后一种情况。可以去查看源代码,首先找到readFile函数所在的声明头文件FileManager.hh,其声明情况如下

 

[cpp] view plaincopyprint?
  1. /** 
  2.    * \brief Read a mesh from a file 
  3.    * 
  4.    *  Returns true if the file was successfully read. The mesh 
  5.    *  is stored in parameter _mesh. If something goes wrong, 
  6.    *  this function returns false. 
  7.    * 
  8.    * @param _filename       The file that is to be read 
  9.    * @param _mesh           A reference to an OpenVolumeMesh instance 
  10.    * @param _topologyCheck  Pass true if you want to perform a topology check 
  11.    *                        each time an entity is added (slower performance) 
  12.    * @param _computeBottomUpIncidences Pass true if you want the file manager 
  13.    *                                    to directly compute the bottom-up incidences 
  14.    *                                    for the mesh. (Note: These are needed for 
  15.    *                                    some iterators to work, see documentation) 
  16.    */  
  17.   template <class MeshT>  
  18.   bool readFile(const std::string& _filename, MeshT& _mesh,  
  19.       bool _topologyCheck = true,  
  20.       bool _computeBottomUpIncidences = trueconst;  

声明没有任何问题,四个参数,但是两个是默认参数的。寻找该函数的实现,在文件FileManagerT.cc中,然后在都头文件的最后又发现如下代码:

[cpp] view plaincopyprint?
  1. #if defined(INCLUDE_TEMPLATES) && !defined(FILEMANAGERT_CC)  
  2. #include "FileManagerT.cc"  
  3. #endif  


错误就在这段代码之中,这段代码的意思是如果定义了INCLUDE_TEMPLATES这个宏并且没有定义FILEMANAGERT_CC(这个是在文件FileManagerT.cc定义,用于避免重定义),问题就出在前一个宏名字上,因为这个宏没有被定义,所以下面这个#include不会被执行,也就是FileManagerT.cc不会被包含在头文件中。而且可以查看到CmakeList.txt(OpenMesh/src/CmakeList.txt)中有下面这一句

[cpp] view plaincopyprint?
  1. # Don't build template cc files as they only contain templates  
  2. acg_drop_templates(sources)  


 

这句话的意思是将所有模板函数的文件剔除工程。

这两个设置会造成最终没有包含进函数的实现,仅仅包含了函数的声明。这样的话一种方法是在你使用函数的时候将*T.cc作为头文件使用#include进自己的代码中,但是这种方法很不安全,因为.cc文件中没有实现头文件保护,或许工程小的时候不会出现重定义,但是工程大了难免有重定义出现,因此不推荐使用这种方法解决该问题,而且在这个工程中有很多模板文件都是这么处理,如果这么修改都要修改其他的文件,而且还要非常清楚什么时候引用这些*T.cc文件。

如果直接按照上面的方法试验的话,将*T.cc添加到自己的工程,原始的link错误会消失,但是伴随而来的是一个函数未定义typeName函数未定义,可以查看这个函数又是工程中另一个模板文件中实现的函数,所以这样错误会一连串的出现。

另一种解决办法是,直接将文件都包含在工程中,去掉CmakeList中的那一行,试验证明不能解决问题,原因未明(在下目前还是小白,囧)。我采用了另外一种思路去解决这个问题,因为通常情况下模板写的函数不需要编译链接(或许这个也是上面删除CmakeList中那一行不成功的原因),因此只要能够将这些模板的函数放到相应的头文件中就完全可以了,而且貌似原始作者也是这么个打算,因为,他们在头文件的最后写了一句条件宏,欲将模板直接引进头文件。

但是问题就出现在这里,他试图引进却因为没有定义宏名而失败,所以我试着将整个工程中所有这个宏名都注释或取消掉,只留下如下格式:

[cpp] view plaincopyprint?
  1. #if /*defined(INCLUDE_TEMPLATES) &&*/ !defined(FILEMANAGERT_CC)  
  2. #include "FileManagerT.cc"  
  3. #endif  


 

这里的!define不能取消,这里它的作用类似于头文件的guid保护。

搜索整个工程中的INCLUDE_TEMPLATES将他们都做类似处理,再次编译链接,会发现链接错误已经消失,问题解决。

分支错误

读取的文件错误,读取的文件是官网提供的例子文件格式如下:

 

[cpp] view plaincopyprint?
  1. OVM ASCII  
  2. Vertices  
  3. 8  
  4. -1.0 -1.0 -1.0  
  5. 1.0 -1.0 -1.0  
  6. 1.0 1.0 -1.0  
  7. -1.0 1.0 -1.0  
  8. -1.0 -1.0 1.0  
  9. 1.0 -1.0 1.0  
  10. 1.0 1.0 1.0  
  11. -1.0 1.0 1.0  
  12. Vertex_Property "Vertex Weights"  
  13. float  
  14. 1.363  
  15. 6.334  
  16. 2.766  
  17. 8.348  
  18. 4.214  
  19. 2.136  
  20. 7.114  
  21. 0.651  
  22. Edges  
  23. 12  
  24. 0 1  
  25. 1 2  
  26. 2 3  
  27. 3 0  
  28. 4 5  
  29. 5 6  
  30. 6 7  
  31. 7 4  
  32. 0 4  
  33. 1 5  
  34. 2 6  
  35. 3 7  
  36. Edge_Property "Edge Tag"  
  37. bool  
  38. 1  
  39. 1  
  40. 0  
  41. 1  
  42. 1  
  43. 0  
  44. 0  
  45. 1  
  46. 0  
  47. 0  
  48. 1  
  49. 1  
  50. Faces  
  51. 6  
  52. 4 0 2 4 6  
  53. 4 8 10 12 14  
  54. 4 18 10 21 3  
  55. 4 16 15 23 6  
  56. 4 20 12 23 5  
  57. 4 0 18 9 17  
  58. Face_Property "Face Selection"  
  59. bool  
  60. 1  
  61. 1  
  62. 0  
  63. 1  
  64. 1  
  65. 0  
  66. HalfFace_Property "HalfFace Constraints"  
  67. double  
  68. 1.22354  
  69. 0.11698  
  70. 1.83562  
  71. 0.19378  
  72. 0.23567  
  73. 1.23565  
  74. 1.23567  
  75. 0.95874  
  76. 0.43532  
  77. 2.22457  
  78. 0.10957  
  79. 1.09758  
  80. Polyhedra  
  81. 1  
  82. 6 1 2 5 6 9 10  


 

正常读取该文件的话会提示:No edge section defined!没有成功读取边信息,看文件结构Vertices应该是没有出错,因为提示不是:No vertex section defined!去看看读文件函数会发现,这个读取过程仅仅处理了文件中的VerticesEdgesFaces以及POLYHEDRA标签,但是文件中海油Vertex_propertyEdge_PropertyFace_Property, HalfFace_Property属性标签,readFile函数根本没有处理,所以会出现上面没有边的提示。因为读取点的时候一切正常,但是按程序顺序,它期待的下一个是Edges但是出现的却是Vertex_Property,所以就告诉你没有边信息,而且它还直接跳出了函数。所以讲所有的Property属性标签去掉之后,再次读取文件,一切正常。

这里读取的文件格式有些不友好,方法更是暴力省事,应该是可以自己添加读取的函数,但是属性的类型竟然是在文件中指定。所以在读取所有格式的文档时候应该需要考虑这些事情,或者可以也不友好的直接指定。

0 0
原创粉丝点击