• Advertisement
Sign in to follow this  

DLL with STL Woes

This topic is 4796 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Having a little extra time this holiday, i decided to compile my engine as a DLL. This is my first experience with DLLs and it has almost made me give up the idea. Previously the code compiled as a static library with no warnings/errors. From the errors, it appears that i need STL to have a dll-interface before my classes can use STL objects. After some thorough searching, i also came across an article on MSDN stating that while there are workarounds to get STL working, i won't be able to use some containers. Most notably std::list and std::deque. To me it is not worth the effort to spend a whole week and change my code so that it may compile to a dll. And not being able to use STL containers? Im sure there is a workaround, but i have not been able to find a solution yet.

Share this post


Link to post
Share on other sites
Advertisement
Yeap, that's about it - you simply cannot use some containers with STL in .dlls. I understand your feelings - it took me a while to figure out the whole using STL in .dlls when I converted my engine into a .dll. There is no work around except make your own container classes instead of using theirs. So for you, it would not be worth the effort to make it into a .dll. I hope this helps a bit.

- Drew

Share this post


Link to post
Share on other sites
I know of STLPort, but can it be used in DLLs?
Would'nt STLPort have the same restrictions as the MSVC implementation?

Share this post


Link to post
Share on other sites
Sure you can:


#ifndef SPRY_INTERNAL_ALLOCATOR_HPP
#define SPRY_INTERNAL_ALLOCATOR_HPP

#include <limits>
#include <windows.h>

namespace Spry
{
namespace Internal
{
template<typename T>
class Allocator
{
public:
typedef T value_type;
typedef value_type* pointer;
typedef const value_type* const_pointer;
typedef value_type& reference;
typedef const value_type& const_reference;
typedef std::size_t size_type;
typedef std::ptrdiff_t difference_type;

public :
template<typename U>
struct rebind
{
typedef Allocator<U> other;
};

public :
explicit Allocator()
{
}

~Allocator()
{
}

explicit Allocator(Allocator const&)
{
}

template<typename U>
explicit Allocator(Allocator<U> const&)
{
}

pointer address(reference r)
{
return &r;
}

const_pointer address(const_reference r)
{
return &r;
}

pointer allocate(size_type cnt, typename std::allocator<void>::const_pointer = 0)
{
return reinterpret_cast<pointer>(HeapAlloc(GetProcessHeap(), 0, (cnt * sizeof (T))));
}

void deallocate(pointer p, size_type)
{
HeapFree(GetProcessHeap(), 0, p);
}

size_type max_size() const
{
return std::numeric_limits<size_type>::max() / sizeof(T);
}

void construct(pointer p, const T& t)
{
new(p) T(t);
}

void destroy(pointer p)
{
p->~T();
p = 0; //unnecessary in this scope, but silences warnings
}

bool operator==(Allocator const&)
{
return true;
}

bool operator!=(Allocator const& a)
{
return !operator==(a);
}
};
}
}

#endif




Use this class as the allocator for whatever STL container you are using:
std::list<Class*, Spry::Internal::Allocator<Class*> > list;

I don't recommend it, but that doesn't stop most people. :) I think too many people worry about making 'extensible' engines through DLLs rather than just finishing what they have.

Share this post


Link to post
Share on other sites
Quote:
Original post by antareus
I think too many people worry about making 'extensible' engines through DLLs rather than just finishing what they have.


Well I think that is kinda of right - but also you have to consider the fact that using an engine via a .dll is more fun than finishing it [smile]. Seriously though , by getting it into a .dll you can use it (the unfinished engine) a lot easier in test projects compared to copy-pasting code - that is if you have a large library.

As for your tip - what does that exactly do? Use STL in a .dll or let you use STLPort?

- Drew

Share this post


Link to post
Share on other sites
It uses the heap that is allocated to the process, instead of the private ones used by the module's C runtime library.

Share this post


Link to post
Share on other sites
I'm rather confused. Where exactly did you read that you cannot use some of STL in a DLL? What compiler is this to do with?

We use STL extensively at work with .NET and most of our code is in DLLs and we've never had any problem.
Maybe you're trying to use it between the DLL and the EXE? Perhaps each STL container should be entirely contained within the DLL or the EXE. i.e. use accessor functions instead of passing the list between DLL & EXE.

Share this post


Link to post
Share on other sites
Quote:
Original post by iMalc
I'm rather confused. Where exactly did you read that you cannot use some of STL in a DLL? What compiler is this to do with?

We use STL extensively at work with .NET and most of our code is in DLLs and we've never had any problem.
Maybe you're trying to use it between the DLL and the EXE? Perhaps each STL container should be entirely contained within the DLL or the EXE. i.e. use accessor functions instead of passing the list between DLL & EXE.


Quote:

Note that you may not export a generalized template. The template must be instantiated; that is, all of the template parameters must be supplied and must be completely defined types at the point of instantiation. For instance "stack<int>;" instantiates the STL stack class. The instantiation forces all members of class stack<int> to be generated.

Also note that some STL containers (map, set, queue, list, deque) cannot be exported. Please refer to the More Information section to follow for a detailed explanation.


MSDN. You have to use IE to view the page - it will not work correctly in FireFox.

- Drew

Share this post


Link to post
Share on other sites
Quote:

Note that you may not export a generalized template. The template must be instantiated; that is, all of the template parameters must be supplied and must be completely defined types at the point of instantiation. For instance "stack<int>;" instantiates the STL stack class. The instantiation forces all members of class stack<int> to be generated.

Also note that some STL containers (map, set, queue, list, deque) cannot be exported. Please refer to the More Information section to follow for a detailed explanation.

This is true, but it doesn't mean you can't use the STL containers. The same code will be generated in both the DLL and EXE for the container, so reading from a list in an EXE that was created in a DLL isn't a problem. Problems occur when you modify the list (adding/removing nodes, changing the value of a node is OK) as this could result in allocating or releasing memory on different heaps (the EXE's and the DLL's)....things start to go *splat*.

antareus's solution prevents this from happening. The allocator object explicitly allocates & releases memory on the EXE's heap, so even if the allocator is called (by the container) from within the DLL the container will always be using the EXE's heap for allocating & releasing memory.

Share this post


Link to post
Share on other sites
Oh I agree - its just you have to jump through a few hoops in order to use some basic things, such as vector. If you use a UDT, you must overload the < and == operator because those tow are used in STL. Furthermore, as MSDN says, you must explicitly instaniate those classes in order to export and use them. I know I have had trouble using string when it was in a parameter list (generated in .dll memory I assume the problem was), so I had to convert to all char*'s. It's too bad it wasn't designed to easily integrate into .dlls :(.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Why would you want to use a .dll? You can't throw exceptions out of them, right? :-( I'd use a static lib... What are the benefits of a dll?

Share this post


Link to post
Share on other sites
Quote:
Original post by joanusdmentia
This is true, but it doesn't mean you can't use the STL containers. The same code will be generated in both the DLL and EXE for the container, so reading from a list in an EXE that was created in a DLL isn't a problem. Problems occur when you modify the list (adding/removing nodes, changing the value of a node is OK) as this could result in allocating or releasing memory on different heaps (the EXE's and the DLL's)....things start to go *splat*.
But you should never have to access the container from both parts. A container can easily only be used only entirely within the DLL. The EXE doesn't need to know (and shouldn't need to know) what kind of data structure the data is held in inside the DLL. It comes down to basic OO design doesn't it? You can use STL entirely within the DLL, and that is what it makes sense to do IMHO. I don't really see that there is a problem.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement