• 如何导出标准模板库(STL)类的实例化和包含STL类对象数据成员的类


    本文翻译自 https://support.microsoft.com/zh-cn/help/168958/how-to-export-an-instantiation-of-a-standard-template-library-stl-clas

    概要

    本文讨论如何实现下面任务:

    • 导出标准模板库(STL)类的实例化。
    • 导出包含STL类对象数据成员的类。

    注意,您无法导出通用的模板,模板必须实例化才能导出。也就是说,必须提供所有的模板参数,并且在实例化时,模板的参数必须是完全定义的类型。例如stack<int>实例化STL堆栈类,实例化时强制生成类stack<int>的所有成员。
    还要注意,一些STL容器(map、set、queue、list、deque)无法导出。

    更多信息

    从VC++ 5.0开始,可以强制对模板类进行实例化并导出实例化类。导出实例化模板类,可使用以下语法:

    导出STL类

    1. .dll.exe文件中,必须链接到相同版本的C运行时库dll。两个都链接msvcrt.lib(Release版本)或都链接到msvcrtd.lib(Debug版本)
    2. dll中,在模板的实例化声明中使用__declspec修饰符,以便从dll中导出STL类的实例化。
    3. exe中,需提供使用extern__declspec修饰的模板实例化声明,以便从dll中导入类。 这会导致警告 C4231 "nonstandard extension used : 'extern' before template explicit instantiation." 。 您可以忽略此警告。

    导出包含STL类对象数据成员的类

    1. .dll.exe文件中,必须链接到相同版本的C运行时库dll。两个都链接msvcrt.lib(Release版本)或都链接到msvcrtd.lib(Debug版本)
    2. dll中,在模板的实例化声明中使用__declspec修饰符,以便从dll中导出STL类的实例化。
      注意:不能跳过上一步,用于创建数据成员的STL类必须导出其实例化。
    3. dll中,在类的声明中使用__declspec修饰符,以便从dll中导出类。
    4. exe中,在类的声明中使用__declspec修饰符,以便从dll中导入类。
      如果要导出的类有一个或多个基类,那么其基类也必须导出。如果要导出的类中还包含某类类型的数据成员,则还必须导出数据成员类型的类。

    注意:一些STL类使用到其它的STL类,这些依赖的类也必须导出。如果使用低于1的警告级别(也就是/W2/W3/W4),则必须导出类会出现在编译器警告信息中。/W4级别编译时,会因为STL而生成大量警告信息,目前不推荐使用此级别警告。

    一些STL类包含嵌套类,所以无法导出这些类。例如,deque包含一个嵌套类deque::iterator如果导出deque,将产生警告信息。,提示你必须导出deque::iterator;如果你导出deque::iterator则会产生警告信息,提示你必须导出deque。这是受限于STL的设计,一旦模板类被实例化,它不能被重新实例化和导出。目前唯一可以导出的STL容器是vector,其它容器(map、set、queue、list、deque)都包含嵌套类无法导出。

    导出使用用户定义类型(UDT)作为STL容器模板参数实例化的类时,必须为自定义类型()UDT)重载<==运算符。例如,如果导出vector<MyClass>,则必须定义MyClass::operator<MyClass::==。这是因为所有的STL容器类都具有成员比较运算操作,需要使用到包含类型的<==运算操作。通常,这些都不被实例化,因为它们没有被使用。当实例化一个模板类时,会生成所有的成员函数,因为STL容器类具有使用到<==的成员函数,所有必须实现它们。如果比较UDT的对象没有意义,也可以在定义operator<opeartor==的时候,简单的返回true

    当在编译期间发现_DLL已经定义(当使用/MD/MDd编译与C运行时库的DLL版本链接时,该符号被隐含定义),以下STL类以及对这些类的操作的各种全局运算符和函数,已在C运行时库DLL中导出。因此,无法从DLL中导出它们。z只要导入类也使用相同的C运行时DLL版本,则不应该导致可执行程序出问题。

    Header      STL template class
    ------------------------------
    <IOSFWD>    basic_ios
    <IOSFWD>    <IOSFWD>
    <IOSFWD>    basic_istream
    <IOSFWD>    basic_string (also typedef'd as string and wstring)
    <IOSFWD>    complex
    <LOCALE>    messages
    <XLOCALE>   codecvt
    <XLOCALE>   ctype
    <XLOCMON>   moneypunct
    <XLOCMON>   money_get
    <XLOCMON>   money_put
    <XLOCNUM>   numpunct
    <XLOCTIME>  time_get
    <XLOCTIME>  time_put
    <XSTRING>   basic_string (also typedef'd as string and wstring)
    

    有关使用哪些模板参数以及声明哪些全局函数和操作符的具体细节,请参阅相关的头文件。

    // -------------------------------------------
       // MYHEADER.H
       //disable warnings on 255 char debug symbols
        #pragma warning (disable : 4786)
       //disable warnings on extern before template instantiation
        #pragma warning (disable : 4231)
    
        #include <vector>
    
        // Provide the storage class specifier (extern for an .exe file, null
        // for DLL) and the __declspec specifier (dllimport for .an .exe file,
        // dllexport for DLL).
        // You must define EXP_STL when compiling the DLL.
        // You can now use this header file in both the .exe file and DLL - a
        // much safer means of using common declarations than two different
        // header files.
        #ifdef EXP_STL
        #    define DECLSPECIFIER __declspec(dllexport)
        #    define EXPIMP_TEMPLATE
        #else
        #    define DECLSPECIFIER __declspec(dllimport)
        #    define EXPIMP_TEMPLATE extern
        #endif
    
        // Instantiate classes vector<int> and vector<char>
        // This does not create an object. It only forces the generation of all
        // of the members of classes vector<int> and vector<char>. It exports
        // them from the DLL and imports them into the .exe file.
        EXPIMP_TEMPLATE template class DECLSPECIFIER std::vector<int>;
        EXPIMP_TEMPLATE template class DECLSPECIFIER std::vector<char>;
    
        // Declare/Define a class that contains both a static and non-static
        // data member of an STL object.
        // Note that the two template instantiations above are required for
        // the data members to be accessible. If the instantiations above are
        // omitted, you may experience an access violation.
        // Note that since you are exporting a vector of MyClass, you must
        // provide implementations for the operator < and the operator ==.
        class DECLSPECIFIER MyClass
        {
        public:
            std::vector<int> VectorOfInts;
            static std::vector<char> StaticVectorOfChars;
    
        public:
            bool operator < (const MyClass > c) const
            {
                return VectorOfInts < c. VectorOfInts;
            }
            bool operator == (const MyClass > c) const
            {
                return VectorOfInts == c. VectorOfInts;
            }
        };
    
        // Instantiate the class vector<MyClass>
        // This does not create an object. It only forces the generation of
        // all of the members of the class vector<MyClass>. It exports them
        // from the DLL and imports them into the .exe file.
        EXPIMP_TEMPLATE template class DECLSPECIFIER std::vector<MyClass>;
    
        // -------------------------------------------
        // Compile options needed: /GX /LDd /MDd /D"EXP_STL"
        //                     or: /GX /LD  /MD  /D"EXP_STL"
        // DLL.CPP
    
        #include "MyHeader.h"
        std::vector<char> MyClass::StaticVectorOfChars;
    
        // -------------------------------------------
        // Compile options needed: /GX /MDd
        //                     or: /GX /MD
        // EXE.CPP
    
        #include <iostream>
        #include "MyHeader.h"
    
        int main ()
        {
            MyClass x;
    
            for (int i=0; i<5; i++) x.VectorOfInts.push_back(i);
            for (char j=0; j<5; j++) x.StaticVectorOfChars.push_back('a' + j);
    
            std::vector<int>::iterator vii = x.VectorOfInts.begin();
            while (vii != x.VectorOfInts.end())
            {
                std::cout << *vii;
                std::cout << " displayed from x.VectorOfInts" << std::endl;
                vii++;
            }
            std::vector<char>::iterator vci = x.StaticVectorOfChars.begin();
            while (vci != x.StaticVectorOfChars.end())
            {
                std::cout << *vci;
                std::cout << " displayed from MyClass::StaticVectorOfChars";
                std::cout << std::endl;
                vci++;
            }
    
            std::vector<MyClass> vy;
            for (i=0; i=5; i++) vy.push_back(MyClass());
    
            return 1;
        }
    

    参考

    其它相关信息,请在VC++帮助中搜索以下关键字:Explicit Instantiation(显示实例化)、__declspec、stack、/MD, /ML, /MT, /LD (Use Run-Time Library)。

  • 相关阅读:
    java入门 (七) 面向对象(三)
    java入门 (七) 面向对象(二)
    java入门 (七) 面向对象(一)
    ajax异步请求,$.each遍历拼接数据
    java入门 (六) 数组(二)
    java入门 (六) 数组(一)
    java入门 (五) 方法
    微信小程序
    776C Molly's Chemicals --- 前缀和
    CF 458C Elections --- 三分|线段树
  • 原文地址:https://www.cnblogs.com/oloroso/p/7271720.html
Copyright © 2020-2023  润新知