471,074 Members | 1,444 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,074 software developers and data experts.

Singleton in native library with C++/CLI

Hi,
I have a large unmanaged static C++ library which I've wrapped using a small
C++/CLR DLL. This is called from a C# client application.

The static library has a singleton, however it appears that it is being
instantiated twice. The first instantiation is down to me calling
singleton.instance() in the C++/CLR DLL, the second instantiation is down to
the library internally calling singleton.instance().

I'm relatively new to C++/CLR, is this expected behaviour and is there
anything I can do to work around this?

Thanks,
Adrian
Jul 11 '06 #1
7 6370
Adrian wrote:
Hi,
I have a large unmanaged static C++ library which I've wrapped using a small
C++/CLR DLL. This is called from a C# client application.

The static library has a singleton, however it appears that it is being
instantiated twice. The first instantiation is down to me calling
singleton.instance() in the C++/CLR DLL, the second instantiation is down to
the library internally calling singleton.instance().

I'm relatively new to C++/CLR, is this expected behaviour and is there
anything I can do to work around this?
I've just converted a small DLL from C++Builder to a C++/CLI DLL in
vs2005 that uses singletons with no real problems. It isn't
instantiated twice for me. The only issue I had was with cleanup. To
destroy the singleton we use std::atexit to register a cleanup func but
in C++/CLI, you have to call _onexit_m (found this because of crashes at
shutdown).

Cheers

Russell
Jul 12 '06 #2
"Russell Hind" <un*****@unknown.comwrote in message
news:OR**************@TK2MSFTNGP03.phx.gbl...
I've just converted a small DLL from C++Builder to a C++/CLI DLL in vs2005
that uses singletons with no real problems. It isn't instantiated twice
for me. The only issue I had was with cleanup. To destroy the singleton
we use std::atexit to register a cleanup func but in C++/CLI, you have to
call _onexit_m (found this because of crashes at shutdown).
Hi,
Unfortunately my situation is more complex than that - I'm calling an
existing static C++ class library which is for all purposes too complex to
convert to C++/CLI from a C++/CLI program.

I've managed to reproduce the problem in a small VS2005 project - I've
uploaded it at http://www.aonaware.eclipse.co.uk/te...gletonTest.zip if
anyone has the time to look. You can see / debug the constructor of the
singleton being called twice. I think it may have something to do with the
template base class for the singleton but I'm not sure...

Thanks,
Adrian


Jul 13 '06 #3
Adrian wrote:
I've managed to reproduce the problem in a small VS2005 project - I've
uploaded it at http://www.aonaware.eclipse.co.uk/te...gletonTest.zip if
anyone has the time to look. You can see / debug the constructor of the
singleton being called twice. I think it may have something to do with the
template base class for the singleton but I'm not sure...
That's interesting. I tried your code, and the constructor is really
called twice.

However, I don't understand why your Settings::internalFunction is
static. Since Settings is a singleton class, it's not really needed to
make any of its members static. I modified your code this way:

Settings.hpp:
void internalFunction();

Settings.cpp:
void Settings::internalFunction()
{
getProperty();
}

Wrapper.h:
static void doSomething() {
Settings::instance().internalFunction();
}

And now it works fine, the constructor is only called once.

I also took a look at your project settings, and noticed that your
SingletonTest.lib is NOT compiled with the /clr. Mixing managed and
unmanaged code can somtimes bring up very subtle problems, as you can
read it at Marcus Heege's blog:

http://www.heege.net/blog/default.as...9-9da8ec9e091e

Read "Avoid native code in managed object files (".obj" files)"

I'm not sure if your problem is related to this in any way, but guess
what. I recompiled your SingletonTest.lib with the /clr settings, then
the rebuilt the dll and the C# code, and the problem disappeared.

So I gave you 2 different workarounds for your problem.

I'm not sure if this glitch is considered a compiler bug, or simply bad
practice, but it certainly looks serious to me.

Tom
Jul 13 '06 #4
Tamas Demjen wrote:
>
Read "Avoid native code in managed object files (".obj" files)"

I'm not sure if your problem is related to this in any way, but guess
what. I recompiled your SingletonTest.lib with the /clr settings, then
the rebuilt the dll and the C# code, and the problem disappeared.

So I gave you 2 different workarounds for your problem.

I'm not sure if this glitch is considered a compiler bug, or simply bad
practice, but it certainly looks serious to me.
Could it be that the singleton is initialised once for native code and
once from managed code? Perhaps there is an issue with statics called
from both?

Cheers

Russell
Jul 14 '06 #5
Adrian wrote:
I've managed to reproduce the problem in a small VS2005 project
I know exactly what's wrong with your project. When you compile a
project with /clr, the default is #pragma managed. When you compile it
without /clr, the default is #pragma unmanaged. Now you can mix the two
things, but you have to make sure that the *same* piece of header file
is compiled with the same settings.

In your project, when you #include "Settings.hpp" and "Singleton.hpp",
the same declaration is compiled as #pragma unmanged in the unmanaged
LIB, and with #pragma managed in the managed DLL. The two things are
*not* byte compatible! You're compiling the same piece of code with
completely incompatible ways, and then link to two things together.

The simplest fix to your problem is to go to Wrapper\Stdafx.h, and
modify it to the following:

#pragma unmanaged
#include "Settings.hpp"
#pragma managed

Please forget my previous message that I sent yesterday. It's not that
it's not correct, but it doesn't show your real problem. Your real
problem is explained in this message.

Just to clarify things. You are not normally required to compile every
native-style class with #pragam unmanaged. You can very easily compile
ISO C++ classes into managed code:

#pragma managed
class NativeClass { }; // generates managed code

However, you're including a non-/clr header file to your /clr project.
You really have to make sure that the compiler settings are matching.

This is the same kind of mistake as putting #ifdef _DEBUG into your
header file, and linking your library project without _DEBUG defined,
but your main application with _DEBUG defined. When the same header file
is compiled with different compiler options, you're calling for trouble.
You can easily lose byte compatibility. This is exactly what happened
with your project -- Singleton.hpp was compiled with one compiler
setting here, and another compiler setting there, and then the two
things were linked together.

Now I can tell for sure that this was definitely not the compiler's
fault. This is something you have to watch carefully when mixing
unmanaged and managed units.

Hope this helps.

Tom
Jul 14 '06 #6
Russell Hind wrote:
Could it be that the singleton is initialised once for native code and
once from managed code?
Exactly. Thanks for the hint -- now I see that the same include file was
compiled into managed code in one project, and into unmanaged code in
the another project. Then the two object files were linked together,
which caused one function call to use a different singleton than the
other function call.

Tom
Jul 14 '06 #7

"Tamas Demjen" <td*****@yahoo.comwrote in message
news:OX**************@TK2MSFTNGP03.phx.gbl...
>
Please forget my previous message that I sent yesterday. It's not that
it's not correct, but it doesn't show your real problem. Your real problem
is explained in this message.
Excellent - thank you very much for this post - it explains my problem
exactly.

Thanks again.

Jul 15 '06 #8

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

7 posts views Thread by Tim Clacy | last post: by
3 posts views Thread by Alicia Roberts | last post: by
6 posts views Thread by ank | last post: by
2 posts views Thread by baba | last post: by
6 posts views Thread by Palvinder Singh | last post: by
1 post views Thread by =?Utf-8?B?RmFiaWFu?= | last post: by
29 posts views Thread by Ugo | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.