1

私は、以下のコードのように定義されたいくつかの静的関数を含む .hpp ファイルを提供するオープン ソース ライブラリを使用しています。

このファイルをプロジェクトに 2 回含めると、シンボルの重複に関するリンカ エラーが常に発生します。関数が 2 回定義されていることはよく知っていますが、これを解決する方法がわかりません。関数 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/ ) の一番下に、この場合、リンカーはエラーを生成すべきではないと書かれています。標準設定のIDEとしてXcodeを使用しています。どうやらここに何か問題があるようです。リンカー エラーは次のようになります。

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 ファイルには、元のファイルの関数の 1 つと同じ名前の関数を定義するファイルが含まれており、それがリンカー エラーの原因であることが判明しました。.hpp ファイルを 1 回インクルードするだけで、なぜこれが最初に機能したのかわかりません。

4

3 に答える 3

0

私はあなたがこれをやったと言ったことを知っていますが、交換してください

static double logcombi(size_t k, size_t n)

inline double logcombi(size_t k, size_t n)

完全に再コンパイルします。

于 2013-05-28T15:10:24.160 に答える
0

ライブラリをヘッダーで配布するのは非常に奇妙なことです。ソース コードにアクセスできるので、対応する cpp ファイルを作成し、ヘッダーからコードをコピーして cpp ファイルに貼り付け、ヘッダー内の関数の本体を削除します。

また、ヘッダーから静的関数を削除します。実際には、エクスポート可能なシンボル (つまり、パブリック関数) を見つけると予想されるファイルに静的 (プライベート) 関数を含めることはあまり意味がありません。

最後に、その hpp ファイルには関数しか含まれていませんか? 定数があれば、それも同様に問題になります。その場合、ヘッダーに extern を付けて宣言を保持し、定数を cpp ファイルに移動します。

大変な作業であることは承知していますが (実際にはそれほど多くはありません)、物事を整理するための唯一の賢明な方法でもあります。

お役に立てれば。

于 2013-05-28T15:18:16.403 に答える
0

私が見る限り、そのような関数は宣言するのと同じ場所に実装します。これが二重包含のエラーの原因です。これまでのところ、2 つの選択肢があります。

  1. Bathshebaが推奨する「インライン」句を使用します。問題は次のとおりです。「インライン」は単なるヒントです。「forceinline」が要求されたとしても、コンパイラは関数をインライン化する試みを拒否する場合があります。あなたのケースは役に立たないため、インライン互換性がないようです。
  2. クライアント コードが .H ファイルをインクルードし、.CPP を含むライブラリとリンクするように、通常の .H + .CPP ペアとして関数を分割します。

ファイルに .H ではなく .HPP という名前を付けても、コンパイラがファイルを処理する方法には何の影響もありません。ファイルに任意の拡張子を使用して、それをヘッダーとして含めることができます。したがって、ここでの命名規則は適切なプログラミング スタイルにすぎません (C/C++ 互換ヘッダーの場合は .H、C++ のみの場合は .HPP)。

于 2013-05-28T22:36:13.247 に答える