OpenVolumeMesh编译的一些错误解决


OpenVolumeMesh
编译的一些错误解决

预备

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

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

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

错误说明

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

#include <OpenVolumeMesh\FileManager\FileManager.hh>
#include <iostream>
#include <string>
#include <OpenVolumeMesh/Geometry/VectorT.hh>
// Hexahedral meshes
#include <OpenVolumeMesh/Mesh/HexahedralMesh.hh>
// Polyhedral meshes
#include <OpenVolumeMesh/Mesh/PolyhedralMesh.hh>
using namespace std;
using namespace OpenVolumeMesh;
int main()
{
	OpenVolumeMesh::GeometricPolyhedralMeshV3f myMesh;
	const string s = "test.poly";
	OpenVolumeMesh::IO::FileManager fm; 
	std::cout << fm.readFile(s, myMesh) << std::endl;
	return 0;
}


 

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

OpenVolumeMesh::IO::FileManager::readFile
)

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,其声明情况如下

 

/**
   * \brief Read a mesh from a file
   *
   *  Returns true if the file was successfully read. The mesh
   *  is stored in parameter _mesh. If something goes wrong,
   *  this function returns false.
   *
   * @param _filename       The file that is to be read
   * @param _mesh           A reference to an OpenVolumeMesh instance
   * @param _topologyCheck  Pass true if you want to perform a topology check
   *                        each time an entity is added (slower performance)
   * @param _computeBottomUpIncidences Pass true if you want the file manager
   *                                    to directly compute the bottom-up incidences
   *                                    for the mesh. (Note: These are needed for
   *                                    some iterators to work, see documentation)
   */
  template <class MeshT>
  bool readFile(const std::string& _filename, MeshT& _mesh,
      bool _topologyCheck = true,
      bool _computeBottomUpIncidences = true) const;

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

#if defined(INCLUDE_TEMPLATES) && !defined(FILEMANAGERT_CC)
#include "FileManagerT.cc"
#endif


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

# Don't build template cc files as they only contain templates
acg_drop_templates(sources)


 

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

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

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

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

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

#if /*defined(INCLUDE_TEMPLATES) &&*/ !defined(FILEMANAGERT_CC)
#include "FileManagerT.cc"
#endif


 

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

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

分支错误

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

 

OVM ASCII
Vertices
8
-1.0 -1.0 -1.0
1.0 -1.0 -1.0
1.0 1.0 -1.0
-1.0 1.0 -1.0
-1.0 -1.0 1.0
1.0 -1.0 1.0
1.0 1.0 1.0
-1.0 1.0 1.0
Vertex_Property "Vertex Weights"
float
1.363
6.334
2.766
8.348
4.214
2.136
7.114
0.651
Edges
12
0 1
1 2
2 3
3 0
4 5
5 6
6 7
7 4
0 4
1 5
2 6
3 7
Edge_Property "Edge Tag"
bool
1
1
0
1
1
0
0
1
0
0
1
1
Faces
6
4 0 2 4 6
4 8 10 12 14
4 18 10 21 3
4 16 15 23 6
4 20 12 23 5
4 0 18 9 17
Face_Property "Face Selection"
bool
1
1
0
1
1
0
HalfFace_Property "HalfFace Constraints"
double
1.22354
0.11698
1.83562
0.19378
0.23567
1.23565
1.23567
0.95874
0.43532
2.22457
0.10957
1.09758
Polyhedra
1
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属性标签去掉之后,再次读取文件,一切正常。

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

 

 

 


 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值