|
I do not think that it is a good idea to export STL objects from a DLL. You may run into memory allocation/deallocation and threading problems.
Drinking In The Sun
Forgot Password?
|
|
|
|
|
Thanks for the reply, but what do you base this on. I have reviewed the "limited" info on MSDN and it seems that you are right, BUT if I can't have objects in my DLLs exported because they use STL, then STL is a HUGE waste of time.
I mean, if I can't take a utility class that uses STL from a console app (or any other EXE for that matter) and put it in a DLL so it can be reused by other apps, what good is STL to me?
Someone please tell me this is not the case.
|
|
|
|
|
There are known problems with std::map. It uses a local static structure to mark nodes. The DLL might have one copy while the EXE will have another. This can cause problems when std::map tries to detect certain conditions based on if a pointer references this static structure.
Templates that don't use static structures or variables should have little problem being exported.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
You can make a thin class wrapper over your class which contains the maps and export the class wrapper instead. The class wrapper will new an instance of your class in its constructor and delete it in the destructor. In this way you can hide the implementation details which are exposed in the header file of your actual clas.
Drinking In The Sun
Forgot Password?
|
|
|
|
|
I have used stl map and set across dlls successfully.
My compiler says on warning C4251:
'class' : multiple copy constructors specified
The class has multiple copy constructors of a single type. The first constructor is used.
I am confused on what your really problem is!
Best regards,
Alexandru Savescu
|
|
|
|
|
According to the MSDN July 2001 (??). If it matters, I am using Visual Studio 6 with SP5.
Compiler Warning (level 1) C4251
'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
The specified base class was not declared with the __declspec(dllexport) keyword.
A base class or structure must be declared with the __declspec(dllexport) keyword if a function in a derived class is to be exported.
|
|
|
|
|
Yes, you are right, I was looking on C:4521
Do you export the classes that the map contains also?
Best regards,
Alexandru Savescu
|
|
|
|
|
|
Another method besides Joaquin suggestion is to utilize the pimpl idiom as mentioned by Herb Sutter (http://gotw.ca[^]) (I believe it's called a compiler firewall in terms of design patterns).
Basically the pimpl (pimpl = pointer to implementation) idiom separates the implementation details from the interface definition.
Look at this class for instance:
class TheClass {
int member;
public:
void DoSomething();
};
All that the clients can do is call DoSomething(). Clients can't touch member, but it can still observe it. This means that all changes to the private parts of the class is visible to all clients - thus you'd have to recompile all depending cpp files.
The pimpl idiom eliminates this by putting the implementation details in the cpp file rather than in the h file.
Example:
struct Impl;
class TheClass {
std::auto_ptr<Impl> pimpl;
public:
TheClass();
void DoSomething();
}; and
struct Impl {
int member;
};
TheClass::TheClass() : pimpl(new Impl) { }
void TheClass::DoSomething() { manipulate(pimpl->member); }
Now you can change anything in your implementation details without the clients noticing it.
From this, it's obvious that you should put the STL-containers in the Impl-struct, thus saving yourself some export-problems.
It's a little bit more typing, but it's a clean way to separate interface from implementation - a very big plus in HUGE projects. (Picture the happy faces on 20 programmers in a project after you've fiddle with the private parts of a common class which many source files depend on.. )
--
standing so tall, the ground behind
no trespassers, on every floor
a garden swing, and another door
she makes it clear, that everything is hers
A place of abode, not far from here, Ms. Van de Veer
|
|
|
|
|
Sort of generic solution to COM.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
Yes it is actually.
And whats even better; I get to call myself a pimpl programmer.
--
standing so tall, the ground behind
no trespassers, on every floor
a garden swing, and another door
she makes it clear, that everything is hers
A place of abode, not far from here, Ms. Van de Veer
|
|
|
|
|
I have some minor points to add, fist, it adds another layer of indirection, so it is slower.
Second, it adds normally 4 or more bytes of overhead, it could be 7(struct {char,struct pimpl* pimpl_}) ,due to alignment on 4 bytes boundaries on 32 bits systems, not counting on the non portable pragmas , it could consume even more memory if a back pointer is used, it have also more performance overhead due to construction/destruction of the pimpl object, even with a custom allocator.
Of course it's great to reduce recompilation time and and protecting from a nasty full rebuild when on large projects,and in some scenarios is a good solution to exception problems, but it must be used with the full notion when to apply or not, it's not the solution for all problems, like .NET is
Cheers,Joao Vaz
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary.-Shog9
Remember just because a good thing comes to an end, doesn't mean that the next one can't be better.-Chris Meech
|
|
|
|
|
Joao Vaz wrote:
I have some minor points to add, fist, it adds another layer of indirection, so it is slower.
Yes it is slower. But not much slower.
Joao Vaz wrote:
it's not the solution for all problems
Well it's a solution for many cases. I'm sure it is possible to hack something up using macros that allows you to use pimpl during debug builds and "straight impl" during release builds. So you can virtually get away with anything.
Joao Vaz wrote:
like .NET is
I like your sense of sarcasm.
--
standing so tall, the ground behind
no trespassers, on every floor
a garden swing, and another door
she makes it clear, that everything is hers
A place of abode, not far from here, Ms. Van de Veer
|
|
|
|
|
Jörgen Sigvardsson wrote:
But not much slower.
Yup, and faster with a custom allocator (normally with placement new suffices)
Jörgen Sigvardsson wrote:
Well it's a solution for many cases.
Fair enough, compilation times much faster, interface more clearly separated since it's a Handle/Body derivative , and useful in providing off-the-self exception safe mechanisms , so it's have a lot of god uses, btw I didn't say the opposite
Jörgen Sigvardsson wrote:
I'm sure it is possible to hack something up using macros that allows you to use pimpl during debug builds and "straight impl" during release builds.
I suggest another alternative, template classes with zero overhead with static release do-nothing dumb functions , a nop that is optimized away by the compiler , for instance ATL uses it (debugging,multithreading ... )
Jörgen Sigvardsson wrote:
I like your sense of sarcasm.
I'm particularly in a good mood, as you known I have been laid off and in the end of november I had to go to the unemployment , the normal cut of expenses reduction mambo jumbo , but yesterday I received my late payments from my former company, my payoff that I'll receive is a nice sum, I received a job offer from the company where I'm developing the product(a great suprise,normally they don't do this, they don't have any programmer and normally all programming work is outsourced, if I accept I'm the only programmer , they have seem all the hard work and late hours that I have being doing ) , and today I'll go to a interview to a company where I didn't send my cv, they have contacted me , because they liked my resume, a bit ironic since of the 25+ cvs that I sent , none of them has obtained a answer .
Finnaly I could use Kylix IDE without problems on a non supported platform(redhat 8.0)after a full week, of fighting against instalation problems ,2 bugs on linux rpm were the reason of instalation problems , then 1 bug on locales, here I downloaded the kylix update and it was fixed, then facing the linux kernel build, due to the fact that the open/save dialogs freezed the ide, and the only fix was to apply the latest stable linux kernel ,then I was faced again with one bug that was breaking my kernel build in the kernel configurator , after the 4 failed attemps to build it up, I achieved sucess , then when I finnaly thought that was over , I catched a nasty bug on GRUB the bootloader of linux because of the particurly combination of ext3 filesystem with the new kernel 2.4.19(a nice kernel panic message of unable to mount root filesystem ...), the bug was fixed by hardcoding the value of the path to the harddisk !!!!!!!!
Now until I see something weird, everything is working fine
So you see, good reasons to be on the good side of the track .
Cheers,Joao Vaz
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary.-Shog9
Remember just because a good thing comes to an end, doesn't mean that the next one can't be better.-Chris Meech
|
|
|
|
|
Joao Vaz wrote:
I suggest another alternative, template classes with zero overhead with static release do-nothing dumb functions , a nop that is optimized away by the compiler , for instance ATL uses it (debugging,multithreading ... )
Got any references to ATL classes? It could be worth the time to investigate the ATL solution.
Joao Vaz wrote:
So you see, good reasons to be on the good side of the track .
It seems as if it's going your way. Good luck on your next job, whatever it may be.
--
standing so tall, the ground behind
no trespassers, on every floor
a garden swing, and another door
she makes it clear, that everything is hers
A place of abode, not far from here, Ms. Van de Veer
|
|
|
|
|
Jörgen Sigvardsson wrote:
Got any references to ATL classes? It could be worth the time to investigate the ATL solution.
ATL internals by Chris Sells ...
From the top of my head, something similar like this:
template <class T> class _NoMT
{
public:
static lock() {};
static unlock() {};
};
template <class T = _NoMT > class CMTServices
{
T* p_;
public:
static lock() {p->lock} ;
static unlock() {p->unlock};
};
template <class T, Class Y= CMTServices> class Xpto
{
Y* lock_;
void foo()
{
lock_->lock();
doSomething();
lock_->unlock();
}
};
Cool eeh ?
Jörgen Sigvardsson wrote:
It seems as if it's going your way. Good luck on your next job, whatever it may be.
Thanks
Cheers,Joao Vaz
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary.-Shog9
Remember just because a good thing comes to an end, doesn't mean that the next one can't be better.-Chris Meech
|
|
|
|
|
Joao Vaz wrote:
Cool eeh ?
Yes, but I don't see how it could be used to hide the interfaces for a pimpl solution. You know, all type variables going into a template must be known when you instantiate it.
--
standing so tall, the ground behind
no trespassers, on every floor
a garden swing, and another door
she makes it clear, that everything is hers
A place of abode, not far from here, Ms. Van de Veer
|
|
|
|
|
Jörgen Sigvardsson wrote:
but I don't see how it could be used to hide the interfaces for a pimpl solution.
Neither do I !!!! (Knocking hard on the floor *grin*) , this thing works well on some situations, but on Pimpl idiom , forget it, at least, I don't know of any crazy idea , duh !!!!! I must drink another coffee
Cheers,Joao Vaz
And if your dream is to care for your family, to put food on the table, to provide them with an education and a good home, then maybe suffering through an endless, pointless, boring job will seem to have purpose. And you will realize how even a rock can change the world, simply by remaining obstinately stationary.-Shog9
Remember just because a good thing comes to an end, doesn't mean that the next one can't be better.-Chris Meech
|
|
|
|
|
I Have some code like this with ATL:
//IHeader is the interface
class CHeader:public IHeader......//IHeader is the interface
{
....
STDMETHOD(get_ID)(/*[out, retval]*/ long *ID);
STDMETHOD(put_ID)(/*[in]*/ long ID);
private:
long m_ID;
}
//IMotoCar is another interface
class CMotoCar:public IMotoCar......
{
....
STDMETHOD(get_Header)(/*[out, retval]*/ IHeader **Header);
STDMETHOD(put_Header)(/*[in]*/ IHeader *Header);
private:
IHeader *m_pHeader;
}
'VB Code
....
dim objHeader as new Header 'IHeader Object
dim objMotoCar as new MotoCar 'IMotoCar Object
dim objHeadref as Header 'reference of objHeader
objHeader.ID=10
objMotoCar.Header=objHeader
set objHeadref=objMotoCar.Header
debug.print objHeadref.ID
.....
but the objHeadref.ID is not 10,oh my God ,why?
|
|
|
|
|
Bob Davis wrote:
oh my God ,why?
Have you traced into the get and put methods to see what happens when they are called ?
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
Hey, at least Logo had, at it's inception, a mechanical turtle. VB has always lacked even that... - Shog9 04-09-2002
During last 10 years, with invention of VB and similar programming environments, every ill-educated moron became able to develop software. - Alex E. - 12-Sept-2002
|
|
|
|
|
Perhaps I should description how i had realized the methods:
//Methods of IHeader
STDMETHODIMP CHeader::get_ID(long *ID)
{
// TODO: Add your implementation code here
*ID=m_ID;
return S_OK;
}
STDMETHODIMP CHeader::put_ID(long ID)
{
// TODO: Add your implementation code here
m_ID=ID;
return S_OK;
}
//Methods of IMotoCar
STDMETHODIMP CMotoCar::get_Header(IHeader **Header)
{
// TODO: Add your implementation code here
*Header=m_pBoundRect;
(*Header)->AddRef();
return S_OK;
}
STDMETHODIMP CMotoCar::put_Header(IHeader *Header)
{
// TODO: Add your implementation code here
m_pHeader=Header;
m_pHeader->AddRef();
return S_OK;
}
when Traced into put method: m_ID=10
when trace into get method :m_ID=0
|
|
|
|
|
Bob Davis wrote:
STDMETHODIMP CMotoCar::get_Header(IHeader **Header)
{
*Header=m_pBoundRect;
(*Header)->AddRef();
return S_OK;
}
STDMETHODIMP CMotoCar::put_Header(IHeader *Header)
{
m_pHeader=Header;
m_pHeader->AddRef();
return S_OK;
}
I think your problem is in get_Header(). In set_Header() you let m_pHeader take a reference, but your get_Header-method returns a reference to a m_pBoundRect object?? It's clearly not symmetric...
Also, you should check m_pHeader in set_Header to see if it already references an object. If it does, it should Release() before you let it refer to another pointer. Can you spell resource leaks?
--
standing so tall, the ground behind
no trespassers, on every floor
a garden swing, and another door
she makes it clear, that everything is hers
A place of abode, not far from here, Ms. Van de Veer
|
|
|
|
|
I'm a newer in Com/ATL.
I have an interface named "IMotoCar",it has a method
GetHeader(/*[out,retval]IHeader **Header).
In this method ,I want to return another interface nameed
"IHeader",b ut how to realize it?
|
|
|
|
|
I believe you can return an IDispatch *, which you'll then have to upcast again at the other end.
Christian
No offense, but I don't really want to encourage the creation of another VB developer. - Larry Antram 22 Oct 2002
Hey, at least Logo had, at it's inception, a mechanical turtle. VB has always lacked even that... - Shog9 04-09-2002
During last 10 years, with invention of VB and similar programming environments, every ill-educated moron became able to develop software. - Alex E. - 12-Sept-2002
|
|
|
|
|
You do like:
STDMETHODIMP CMotoCar::GetHeader( IHeader** pHeader)
{
*pHeader = m_pHeader;
if(*pHeader)
(*pHeader)->AddRef();
return S_OK;
}
May I advise you to pick up a book on COM?
--
standing so tall, the ground behind
no trespassers, on every floor
a garden swing, and another door
she makes it clear, that everything is hers
A place of abode, not far from here, Ms. Van de Veer
|
|
|
|
|