2013-05-28 48 views
0

我正在使用一个开源库,它提供了一个.hpp文件,其中定义了几个静态函数,如下面的代码。C++链接器错误与.hpp文件中的静态函数

当我在项目中包含这个文件两次时,我总是得到一个链接器错误,抱怨重复的符号。我很清楚这个功能被定义了两次,但我不知道如何解决这个问题。我试图标记extern或inline函数而没有成功。

解决此问题的最佳方法是什么?

#ifndef OPENMVG_ROBUST_ESTIMATOR_ACRANSAC_H_ 
#define OPENMVG_ROBUST_ESTIMATOR_ACRANSAC_H_ 

#include <algorithm> 
#include <cmath> 
#include <iterator> 
#include <vector> 
#include <limits> 
#include <iostream> 

#include "openMVG/robust_estimation/rand_sampling.hpp" 

namespace openMVG { 
namespace robust{ 

static double logcombi(size_t k, size_t n) 
{...} 

... 

编辑:我忘了说,也有模板的功能,这意味着我不能使用的.h和.cpp文件。所以这就是他们使用.hpp文件的原因。在这个页面(http://www.cplusplus.com/doc/tutorial/templates/)的底部,它表示链接器在这种情况下不应该产生错误。我使用Xcode作为标准设置的IDE。显然这里有什么问题。链接器错误是这样的:

duplicate symbol __ZN7openMVG6robust13UniformSampleEmmPSt6vectorImSaImEE in: 
    /Users/chris/Library/Developer/Xcode/DerivedData/SfM_OpenMVG-dgkssozpvorbpphdefdpurfpdaqv/Build/Intermediates/SfM_OpenMVG.build/Debug/SfM_incremental_unified.build/Objects-normal/x86_64/SfMIncrementalEngine.o 
    /Users/chris/Library/Developer/Xcode/DerivedData/SfM_OpenMVG-dgkssozpvorbpphdefdpurfpdaqv/Build/Intermediates/SfM_OpenMVG.build/Debug/SfM_incremental_unified.build/Objects-normal/x86_64/computeMatches.o 
ld: 1 duplicate symbol for architecture x86_64 
clang: error: linker command failed with exit code 1 (use -v to see invocation) 

分辨率:事实证明的HPP文件我指的是包含具有相同名称的功能定义为用的原始文件的功能之一和文件这是导致链接器错误的原因。我不知道为什么这个工作在第一时间只是包含.hpp文件一次。

+0

当询问编译器/链接器错误时,请始终在您的问题中包含实际的错误消息。或者,如果其中有太多(数百),相关的前几个和最后几个。 – Angew

+0

我也有过相同的错误。如果'静态'并不意味着很多。刚刚删除它。 – mr5

回答

0

我知道你说你有

inline double logcombi(size_t k, size_t n) 

完全重新编译做到了这一点,但更换

static double logcombi(size_t k, size_t n) 

+0

我再次尝试过,但没有任何运气。错误仍然存​​在。 – Chris

+0

明天上传整件事,生病看看。链接C++代码总是可能的;最终 – Bathsheba

+0

非常感谢!您可以在这里获得hpp文件:https://github.com/openMVG/openMVG/tree/master/src/openMVG/robust_estimation(名称为“robust_estimator_ACRansac.hpp”。它包含来自同一目录的另一个文件。 )就像我说过的,当我将文件包含在至少两个其他文件中时,只有一个问题。 – Chris

0

分发你的库在一个头是一件很奇怪的事情。由于您可以访问源代码,我只需创建相应的cpp文件,复制&将标题中的代码粘贴到cpp文件,然后删除标题中函数的主体。

我也会从头文件中移除静态函数:在您期望找到可导出符号(即公共函数)的文件中有一个静态(专用)函数没有多大意义。

最后,你确定这个hpp文件中只有函数吗?如果存在常量,则同样存在问题。在这种情况下,我会在头文件中使用extern保留声明,并将常量移到cpp文件中。

我知道,这是很多工作(实际上并非如此),但它也是安排事物的唯一明智的方式。

希望这会有所帮助。

+0

我编辑了我的问题。事实证明,这是因为模板功能无法完成的。 – Chris

0

就我所见,您可以在您声明它们的相同位置实现这些功能。这是双重包含错误的原因。到目前为止,你有两个选择:

  1. 录用“内联”所推荐的拔示巴条款。问题是:“内联”只是一个提示。即使“forceinline”被问到,编译器也可能会拒绝尝试内联函数。看起来,你的情况不是内联兼容的,因为它不能帮助你。
  2. 拆分功能照常.H + .CPP对,以便客户端代码将包括.H文件,然后用含有.CPP

一个lib链接其实你命名你的文件.HPP而不是与编译器对待它的方式没有任何关系。您可以对文件使用任意扩展名,然后将其包含为标题。因此,这里的命名约定不过是很好的编程风格(对于C/C++兼容的头文件,.HPP仅适用于C++)。