Managed/Unmanaged code and #pragma managed/unmanaged

A

ajtaylor

Hello,

I am hoping someone can clear up some confusion I have as seemingly
(like all things C++/CLI it seems) there isn't too much information
out there.

I have a load of unmanaged C++ that has been built up over the years
and performs well. I have some C++/CLI code that uses this unmanaged
code seemingly quite well (although I do worry that the performance is
not as good as it should be due to my lack of knowledge)

The unmanaged C++ code uses a lot of BOOST stuff and this raises other
issues (more on that later).

The setup I have is the unmanaged code is in a series of .LIBs. I then
have a /CLR compiled project that links against these libs. I mainly
have classes in the /CLR project that creates a managed wrapper for
the unmanaged code. Then I have some ASP.NET code that uses this
assembly.

The questions I have on this setup are:-

(1) Should I be wrapping #included UNMANAGED headers with #pragma
unmanaged, #pragma managed block? (I currently do - but read on MSDN
and on this newsgroup that this is a no-no)

The reason I ask is I cant get my head around what the compiler will
do when it encounters one of my unmanaged headers in a file compiled
with /CLR. I am particularly concerned as I use things like
boost::shared_ptr in my unmanaged code. Does the /CLR option cause the
compiler to try to convert the included stuff into C++/CLI compatible
code?

One of my reasons for doing this was that I was getting no end of
grief trying to use BOOST 1_34_1 and this thread (see at the bottom)

http://www.thescripts.com/forum/thread701525.html

Suggested this approach.

(2) If say I have a std::vector containing a load of pointers (well
boost::shared_ptrs) is there any harm in passing this around C++/CLI
Managed code?

What I wonder is if I am providing a wrapper class for the unmanaged
code am I expected to extract all the data from the std::vector and
put it into managed structures? So that the #includes for unmanaged
code is only in one cpp file (say)?

Many thanks for your time.

A.
 
B

Ben Voigt [C++ MVP]

Hello,

I am hoping someone can clear up some confusion I have as seemingly
(like all things C++/CLI it seems) there isn't too much information
out there.

I have a load of unmanaged C++ that has been built up over the years
and performs well. I have some C++/CLI code that uses this unmanaged
code seemingly quite well (although I do worry that the performance is
not as good as it should be due to my lack of knowledge)

The unmanaged C++ code uses a lot of BOOST stuff and this raises other
issues (more on that later).

The setup I have is the unmanaged code is in a series of .LIBs. I then
have a /CLR compiled project that links against these libs. I mainly
have classes in the /CLR project that creates a managed wrapper for
the unmanaged code. Then I have some ASP.NET code that uses this
assembly.

The questions I have on this setup are:-

(1) Should I be wrapping #included UNMANAGED headers with #pragma
unmanaged, #pragma managed block? (I currently do - but read on MSDN
and on this newsgroup that this is a no-no)

That works well for me. I'm actually trying to prevent any managed code
from running on a particular thread, to prevent the GC from pausing it.

Can you provide a link to the MSDN article which you think discourages this?
 
A

ajtaylor

That works well for me. I'm actually trying to prevent any managed code
from running on a particular thread, to prevent the GC from pausing it.

Can you provide a link to the MSDN article which you think discourages this?

http://msdn2.microsoft.com/en-us/library/0adb9zxe.aspx

Use the following guidelines when applying these pragmas:


Add the pragma preceding a function but not within a function
body.
Add the pragma after #include statements (do not use these
pragmas before #include statements).

Also in the book Expert C++/CLI by Marcus Heege P170

He basically recommends that you don't do it.
 
B

Ben Voigt [C++ MVP]

http://msdn2.microsoft.com/en-us/library/0adb9zxe.aspx
Use the following guidelines when applying these pragmas:


Add the pragma preceding a function but not within a function
body.

This is because any function is either native or managed, you can't mix.

(However a template function might be able to create some native
instantiations and some managed instantiations from the same source, but
there still is no mixing).
Add the pragma after #include statements (do not use these
pragmas before #include statements).

Ideally the header files should contain the pragma managed push/pop, this
helps ensure that any particular declaration has the same pragma in effect
in every compilation unit.

For purely native third-party headers, rather than modify the third-party
headers, you might have to place the pragma before a #include. To help
ensure this is done consistently, create a wrapper header file that sets
pragmas correctly (including managed, packing, etc), then includes the
unmodified third-party header.
Also in the book Expert C++/CLI by Marcus Heege P170

He basically recommends that you don't do it.

In some situations it may be unavoidable. In other cases it may help work
around a compiler bug.
 
A

ajtaylor

This is because any function is either native or managed, you can't mix.

(However a template function might be able to create some native
instantiations and some managed instantiations from the same source, but
there still is no mixing).


Ideally the header files should contain the pragma managed push/pop, this
helps ensure that any particular declaration has the same pragma in effect
in every compilation unit.

For purely native third-party headers, rather than modify the third-party
headers, you might have to place the pragma before a #include. To help
ensure this is done consistently, create a wrapper header file that sets
pragmas correctly (including managed, packing, etc), then includes the
unmodified third-party header.





In some situations it may be unavoidable. In other cases it may help work
around a compiler bug.


Thanks for your reply.

What I don't understand is I have created two assemblies and they both
follow a simple design

ManagedClass contains an unmanaged ptr to an unmanaged class. This
managed class provides a managed interface to some unmanaged code
(this is compiled with /clr).

The unmanaged class has a simple interface and only uses std::string
over and above doubles/ints etc... In the implementation of this class
(in the cpp file) more complex unmanaged types are used (including
BOOST). This is all compiled as unmanaged C++

The Only #include in the unmanaged C++ class header file is #include
<string>

Now, I use one of these assemblies and all works fine. The other one
crashes with the

is not a valid Win32 application. (Exception from HRESULT: 0x800700C1)

error.

The only way to solve this is to wrap the #include of the unmanaged
header with the pragmas in the managed class implementation file.

ManagedClass.cpp

#pragma unmanaged
#include "UnManaged.h"
#pragma managed

Fair enough if this is the way you have to do it - but

a) Its inconsistent the fact that one assembly works and the other
doesn't despite being almost identical in code (and certainly
identical in design)
b) I though IJW should "just work" I can see how including a
unmanaged c++ header that #includes a std::string should cause runtime
crashes unless I use the #pragrmas.

I am finding C++/CLI development incredibly frustrating to say the
least.

Many thanks.

A
 
T

Tamas Demjen

The only way to solve this is to wrap the #include of the unmanaged
header with the pragmas in the managed class implementation file.

ManagedClass.cpp

#pragma unmanaged
#include "UnManaged.h"
#pragma managed

If UnManaged.h is your own source code (not 3rd party), I recommend that
you put the following there:

#ifdef _MANAGED
#pragma managed(push, off)
#endif

#include ... // your unmanaged includes

class ... // your unmanaged classes

#ifdef _MANAGED
#pragma managed(pop)
#endif

This is what Ben meant by "pragma managed push/pop".

This way you can simply #include "UnManaged.h" from managed code.

There are many subtle details when you mix managed and unmanaged code.
Here's one more thing that you should watch out for:
http://tinyurl.com/ytlyqd

Tom
 
A

ajtaylor

If UnManaged.h is your own source code (not 3rd party), I recommend that
you put the following there:

#ifdef _MANAGED
#pragma managed(push, off)
#endif

#include ... // your unmanaged includes

class ... // your unmanaged classes

#ifdef _MANAGED
#pragma managed(pop)
#endif

This is what Ben meant by "pragma managed push/pop".

This way you can simply #include "UnManaged.h" from managed code.

There are many subtle details when you mix managed and unmanaged code.
Here's one more thing that you should watch out for:http://tinyurl.com/ytlyqd

Tom

Thanks for the reply. I will add that to my code and see if that cures
the inconsistencies I am seeing.

BTW: I think some of my issues are stemming from using BOOST in my
code and it seems that I only started seeing these issues when I went
to SP1 in VS2005.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top