How to open an STL list on a DLL boundary?

I have a DLL that needs to access data stored in STL containers in a host application. Since C ++ does not have a standard ABI, and I want to support different compilers, the interface between the application and the DLL should basically remain normal-old.

For vectors, this is relatively simple. You can simply return the vector memory block, because it is guaranteed to be free:

// To return vector<int> data virtual void GetVectorData(const int*& ptr, size_t& count) const { if (!vec.empty()) ptr = &(vec.front()); count = vec.size(); } 

Now the DLL can have read-only secure access to vector data through this interface. The DLL can also wrap this in order to copy the contents into a vector for itself.

What about STLs (and deques)? Is there another easy way to allow cross-border DLL access? Or do I need to resort to some interface GetFirst () / GetNext ()? I may need to do this for a large number of lists, so it would be nice to have a solution as simple as a vector.

+8
c ++ list stl abi pod
source share
3 answers

Perhaps you can pass something like β€œhandles” to list / deque iterators? These types of descriptors will be opaque and declared in the header file that you send to users. Inside, you will need to map the descriptor values ​​for the list / deque iterators. Basically, the user should write code, for example:

 ListHandle lhi = GetListDataBegin(); const ListHandle lhe = GetListDataEnd(); while (lhi != lhe) { int value = GetListItem(lhi); ... lhi = GetNextListItem(lhi); } 
+7
source share

You can pass stl objects between DLLs and support different compilers if you are careful when you instantiate each type of stl. You need some intelligent DLLEXPORT macros β€” I use the following set to successfully support VC and gcc.

 #ifdef WIN32 #ifdef MYDLLLIB_EXPORTS // DLL export macros #define MYDLLLIB_API __declspec(dllexport) #define MYDLLLIB_TEMPLATE #else #define MYDLLLIB_API __declspec(dllimport) #define MYDLLLIB_TEMPLATE extern #endif #else // Not windows --- probably *nix/bsd #define MYDLLLIB_API #ifdef MYDLLLIB_EXPORTS #define MYDLLLIB_TEMPLATE #else #define MYDLLLIB_TEMPLATE extern #endif #endif // WIN32 

When compiling your DLL, define MYDLLLIB_EXPORTS. In a DLL, you can instantiate each type of stl that you want to use, such as lists or string vectors

 MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::vector<std::string>; MYDLLLIB_TEMPLATE template class MYDLLLIB_API std::list<std::string>; 

Consumers of your DLL (for which MYDLLLIB_EXPORTS are not defined) will see

 extern template class __declspec(dllimport) std::vector<std::string>; 

and use the binary code exported from your DLL, instead of creating your own.

+10
source share

the interface between the application and the DLL should basically remain sore-handed.

Not necessary. You must be sure to use the same version of the compiler. In addition, the assembly parameters that affect the layout of STL objects exactly match between the DLL and the application.

If you have to release the dll into the wild, you are right to deal with the disclosure of STL across dll boundaries. If, however, everything is under your control and purely internal (or if you can firmly apply third-party build settings / compiler), you should be fine.

+1
source share

Source: https://habr.com/ru/post/639894/


All Articles