6

Win7 で VS2008 を使用し、CentOS 18 で g++ 4.7 を使用しています。この問題は、動的共有ライブラリを使用した場合に Windows でのみ発生します。静的ライブラリに変換すると、プログラムは正常にリンクします。

共有ライブラリ テンプレート関数/クラスでは、ヘッダー ファイルで定義するか、テンプレート タイプ (パラメーター) のテンプレート インスタンス化をコンパイル ユニットを介して提供する必要があることを理解しています。私は後者のオプションを選択しました。私は前にそれをやったことがあります、私は経験しました

テンプレートをヘッダー ファイルにしか実装できないのはなぜですか?

テンプレートを使用した C++ 共有ライブラリ: 未定義のシンボル エラー

しかし、Windows でライブラリを dll に変換するとすぐにシンボルの解決に失敗した理由がわかりません: error LNK2019: unresolved external symbol "void __cdecl HelpingRegistration(double)" (??$HelpingRegistration@N@@YAXN@Z)関数 _main で参照

Windows では、静的ライブラリで問題なく動作します。Linux では、動的ライブラリと共有ライブラリの両方が機能します。

//Static library
//Library header
#ifndef _TEMPLATED_STATIC_LIB_
#define _TEMPLATED_STATIC_LIB_

#include <iostream>
#include <string>
#include "Export.h"

template<typename T>
class EXPORT TemplatedStaticLib
{
public:
    TemplatedStaticLib(){};
    ~TemplatedStaticLib(){};

    void print(T t);

};

template<typename T>
EXPORT void HelpingRegistration(T);

#endif

// ライブラリ .cpp

#include "TemplatedStaticLib.h"
#include <typeinfo>


template<typename T>
void TemplatedStaticLib<T>::print(T t)
{
    std::cout << "Templated Print: "<< t<< " type:: "  << typeid(t).name() << std::endl;
}

//Class Template explicit instantiation
template class TemplatedStaticLib<double>;
template class TemplatedStaticLib<std::string>;

template<typename T>
void  HelpingRegistration(T t)
{
    std::cout << "Function Templated Print: "  << t << " type: " << typeid(t).name() << std::endl;
       //return t;
}

//function template explicit instantiation
template void HelpingRegistration<>( double );
template void HelpingRegistration<>( std::string );

//Windows シンボル エクスポータ

//.h

#ifndef STATIC_LIB_EXPORT
#define STATIC_LIB_EXPORT

#if !defined WIN32
    #define EXPORT
#elif defined LIB_EXPORTS
    #define EXPORT __declspec(dllexport)
#else
    #define EXPORT __declspec(dllimport)
#endif

//STATIC_LIB_EXPORT
#endif

// ライブラリ ユーザー .cpp

#include <TemplatedStaticLib/TemplatedStaticLib.h>

#include<string>

int main(int argc, char* argv[])
{
    double aDouble = 3.9;
    TemplatedStaticLib<double> double_test; 
    double_test.print(aDouble);

    std::string aString = "James";
    TemplatedStaticLib<std::string> string_test; 
    string_test.print(aString);

    HelpingRegistration(aDouble);
    HelpingRegistration(aString);


    return 0;
}
4

3 に答える 3

4

スペシャライゼーションをエクスポートする必要があると思います。.cpp ファイルでこれを試しましたか:

template class EXPORT TemplatedStaticLib<double>;
template class EXPORT TemplatedStaticLib<std::string>;

ヘッダーでもほぼ同じです:

template class EXPORT TemplateStaticLib<double>;
template class EXPORT TemplateStaticLib<std::string>;

EXPORT マクロで動作すると思います(.cpp ファイルが表示__declspec(dllexport)され、ヘッダーが表示されると仮定します__declspec(dllimport))。私は Windows の専門家ではないことを認めます__declspec

私はインターウェブ上のこの他の回答から私の回答を得たことを認めます : -export-from-dll (Franjo555 の最終バージョンの一番下までスクロールします。)

于 2013-07-08T06:44:04.377 に答える
3

私は問題を解決しました。Windows の下では、クラス テンプレートと関数テンプレートが別々にエクスポートされ、ネット上で興味深い読み物があります。

クラス テンプレートが翻訳単位 (.cpp) でインスタンス化されている場合、VS コンパイラはクラス テンプレート シンボルをエクスポートします。

ただし、関数テンプレートの場合、シンボルがダイナミック ライブラリに存在するためには、キーワード '__declspec(dllexport)' が明示的に存在する必要があります。

例えば

template EXPORT void HelpingRegistration<double>( double );
//EXPORT is defined as __declspec(dllexport) 

これは、VS が別の方法で決定する別のケースです。ここに興味深い読み物があります: http://www.codesynthesis.com/~boris/blog/2010/01/18/dll-export-cxx-templates/

于 2013-07-08T12:56:01.457 に答える
0

これは、テンプレート クラスが特定のパラメーターで最初に使用されたときに、コンパイラがテンプレート クラスに特化したコードを作成するためだと思います。コンパイラは、コンパイル ユニット (.cpp ファイル) をコンパイルするときにインクルードされたヘッダー ファイル (.h) のみを使用するため、すべての tmplate コードは .h ファイルで使用できる必要があります。特殊なテンプレート クラスは dll からエクスポートできますが、テンプレート クラス自体はエクスポートできません。

于 2014-03-21T18:01:15.760 に答える