One way of eliminating C4251 warning when using stl-classes in the dll-interface

后端 未结 4 1359
猫巷女王i
猫巷女王i 2020-12-08 01:08

It is not a good practice using stl-classes in the dll-interface as Common practice in dealing with warning c4251: class … needs to have dll-interface explains. An example i

相关标签:
4条回答
  • 2020-12-08 01:34

    I think you've got at least 5 possible options to solve this problem:

    1. You could still keep STL/template classes for your fields and also use them as parameter types, as long as you keep all the fields private (which is a good practice anyway). Here is a discussion about this. To remove the warnings you could simply use according #pragma statements.

    2. You could create small wrapper classes with private STL fields and expose fields of your wrapper class types to the public instead, but this would most probably only move the warnings to another places.

    3. You could use the PIMPL idiom to hide your STL fields in a private implementation class, which will not even be exported from your library nor be visible outside of it.

    4. Or you could actually export all the required template class specializations, as suggested in the C4251 warning, in a way that is described here. In short you would have to insert following lines of code before your HelloWorld class:

      ...
      #include <vector>
      
      template class __declspec(dllexport) std::allocator<int>;
      template class __declspec(dllexport) std::vector<int>;
      template class __declspec(dllexport) std::string;
      
      class __declspec(dllexport) HelloWorld
      ...
      

      By the way, the order of those exports seems to be important: the vector class template uses the allocator class template internally, so the allocator instantiation has to be exported before the vector instantiation.

    5. The direct use of intrinsics is probably your worst option, but if you encapsulate your fields

      int *p_abc;
      int abc_len;
      

      in something like class MyFancyDataArray and the fields

      char *p_str;
      int str_len;
      

      in something like class MyFancyString, then this would be a more decent solution (similar to the one described at the second point). But it is probably not the best habit to reinvent the wheel too often.

    0 讨论(0)
  • 2020-12-08 01:46

    I'm not sure which problem you want to solve here. There are two different issues: Cross compiler binary compatibility and avoiding "undefined symbol" linker errors. The C4251 warning you quoted talks about the second issue. Which is really mostly a non-issue, especially with SCL classes like std::string and std::vector. Since they're implemented in the CRT, as long as both sides of your application use the same CRT, everything will "just work". The solution in that case is to just disable the warning.

    Cross compiler binary compatibility OTOH, which is what is discussed in the other stackoverflow question you linked, is a whole different beast. For that to work out, you basically have to keep all your public header files free of any mention of any SCL class. Which means you either have to PIMPL everything or use abstract classes everywhere (or a mix thereof).

    0 讨论(0)
  • 2020-12-08 01:55

    OR do the easiest thing to do, move the __declspec to the ONLY members you care to export:

    class HelloWorld
    {
    public:
        __declspec(dllexport) HelloWorld()
        {
            abc.resize(5);
            for(int i=0; i<5; i++)
                abc[i] = i*10;
    
            str="hello the world";
        }
        __declspec(dllexport) ~HelloWorld()
        {
        }
        std::vector<int> abc;
        std::string str;
    };
    
    0 讨论(0)
  • 2020-12-08 01:59

    Just use Pointer To Implementation (pImpl) idiom.

    0 讨论(0)
提交回复
热议问题