<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.asp.net/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Miscellaneous Debris : C++/CLI</title><link>http://weblogs.asp.net/avnerk/archive/tags/C_2B002B002F00_CLI/default.aspx</link><description>Tags: C++/CLI</description><dc:language>en</dc:language><generator>CommunityServer 2007 SP1 (Build: 20510.895)</generator><item><title>Tales from the Unmanaged Side – System.String –&gt; char* (pt. 2)</title><link>http://weblogs.asp.net/avnerk/archive/2009/01/13/tales-from-the-unmanaged-side-system-string-gt-char-pt-2.aspx</link><pubDate>Tue, 13 Jan 2009 15:04:17 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6833885</guid><dc:creator>Avner Kashtan</dc:creator><slash:comments>0</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/avnerk/rsscomments.aspx?PostID=6833885</wfw:commentRss><comments>http://weblogs.asp.net/avnerk/archive/2009/01/13/tales-from-the-unmanaged-side-system-string-gt-char-pt-2.aspx#comments</comments><description>&lt;p&gt;A while ago, I &lt;a href="http://weblogs.asp.net/avnerk/archive/2007/08/28/more-tales-from-the-unmanaged-side-system-string-gt-char.aspx"&gt;posted an entry&lt;/a&gt; about marshalling a managed System.String into an unmanaged C string, specifically a plain char*. The solution I suggested, back in 2007, involved calling Marshal::StringToHGlobalAuto method to allocate memory and copy the string data into it, and then cast the HGlobal pointer into a char*. &lt;/p&gt;  &lt;p&gt;It seems that in Visual Studio 2008 a new way of doing it was added, as part of the new &lt;a href="http://msdn.microsoft.com/en-us/library/bb384865.aspx"&gt;Marshalling Library&lt;/a&gt;. This library provides a whole set of conversions between System.String and popular unmanaged string representations, like char*, wchar_t*, BSTR, CStringT&amp;lt;wchar_t&amp;gt; and others I am even less familiar with. &lt;/p&gt;  &lt;p&gt;The smarter string representations, like std::string, have their own destructors so I can carelessly let them drop out of scope without worrying about leaks. The more primitive ones, like char*, need to be explicitly released, so that’s why the Marshalling Library contains a new (managed) class called marshal_context which gives me exactly this explicit release.&lt;/p&gt;  &lt;p&gt;Let’s compare my old code with the new:&lt;/p&gt;  &lt;div class="csharpcode"&gt;   &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;&lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;* unmanagedString = NULL;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;&lt;span class="kwrd"&gt;try&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   4:  &lt;/span&gt;    String^ managedString = gcnew String(&lt;span class="str"&gt;&amp;quot;managed string&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   5:  &lt;/span&gt;    &lt;span class="rem"&gt;// Note the double cast.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   6:  &lt;/span&gt;    unmanagedString = (&lt;span class="kwrd"&gt;char&lt;/span&gt;*)(&lt;span class="kwrd"&gt;void&lt;/span&gt;*)Marshal::StringToHGlobalAnsi(managedString);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   7:  &lt;/span&gt;}&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   8:  &lt;/span&gt;&lt;span class="kwrd"&gt;finally&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   9:  &lt;/span&gt;{&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  10:  &lt;/span&gt;    &lt;span class="rem"&gt;// Don't forget to release. Note the ugly casts again.&lt;/span&gt;&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;  11:  &lt;/span&gt;    Marshal::FreeHGlobal((IntPtr)(&lt;span class="kwrd"&gt;void&lt;/span&gt;*)unmanagedString);&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;  12:  &lt;/span&gt;}&lt;/pre&gt;
&lt;/div&gt;
&lt;style type="text/css"&gt;
.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }&lt;/style&gt;

&lt;p&gt;And the new:&lt;/p&gt;

&lt;div class="csharpcode"&gt;
  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   1:  &lt;/span&gt;marshal_context^ context = gcnew marshal_context();&lt;/pre&gt;

  &lt;pre&gt;&lt;span class="lnum"&gt;   2:  &lt;/span&gt;String^ managedString = gcnew String(&lt;span class="str"&gt;&amp;quot;managed string&amp;quot;&lt;/span&gt;);&lt;/pre&gt;

  &lt;pre class="alt"&gt;&lt;span class="lnum"&gt;   3:  &lt;/span&gt;&lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;* unmanagedString = context-&amp;gt;marshal_as&amp;lt;&lt;span class="kwrd"&gt;const&lt;/span&gt; &lt;span class="kwrd"&gt;char&lt;/span&gt;*&amp;gt;( managedString );&lt;/pre&gt;

  &lt;pre&gt;&amp;#160;&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Much shorter, I’m sure you’ll agree. And neater – no need for all the icky, icky casting between different pointer types. And most importantly, I don’t have to explicitly release the char* – the marshal_context class keeps a reference to all the strings that were marshalled through it, and when it goes out of scope its destructor makes sure to release them all. Very efficient, all in all.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6833885" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/avnerk/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/CodeSnippets/default.aspx">CodeSnippets</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2B002B002F00_CLI/default.aspx">C++/CLI</category></item><item><title>Upgrading all projects to .NET 3.5</title><link>http://weblogs.asp.net/avnerk/archive/2008/05/25/upgrading-all-projects-to-net-3-5.aspx</link><pubDate>Sun, 25 May 2008 08:56:14 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:6219753</guid><dc:creator>Avner Kashtan</dc:creator><slash:comments>2</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/avnerk/rsscomments.aspx?PostID=6219753</wfw:commentRss><comments>http://weblogs.asp.net/avnerk/archive/2008/05/25/upgrading-all-projects-to-net-3-5.aspx#comments</comments><description>&lt;p&gt;A simple macro to change the Target Framework for a project from .NET 2.0 to .NET 3.5, hacked together in a few minutes. This will fail for C++/CLI projects, and possibly VB.NET projects (haven't checked). Works fine for regular C# projects, as well as web projects:&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;div&gt;   &lt;pre style="padding-right: 0px; padding-left: 0px; font-size: 8pt; padding-bottom: 0px; margin: 0em; overflow: visible; width: 100%; color: black; border-top-style: none; line-height: 12pt; padding-top: 0px; font-family: consolas, &amp;#39;Courier New&amp;#39;, courier, monospace; border-right-style: none; border-left-style: none; background-color: #f4f4f4; border-bottom-style: none"&gt;&lt;span style="color: #0000ff"&gt;For&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Each&lt;/span&gt; proj &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; Project &lt;span style="color: #0000ff"&gt;In&lt;/span&gt; DTE.Solution.Projects
   &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;
       proj.Properties.Item(&lt;span style="color: #006080"&gt;&amp;quot;TargetFramework&amp;quot;&lt;/span&gt;).Value = 196613
       Debug.Print(&lt;span style="color: #006080"&gt;&amp;quot;Upgraded {0} to 3.5&amp;quot;&lt;/span&gt;, proj.Name)
   &lt;span style="color: #0000ff"&gt;Catch&lt;/span&gt; ex &lt;span style="color: #0000ff"&gt;As&lt;/span&gt; Exception
       Debug.Print(&lt;span style="color: #006080"&gt;&amp;quot;Failed to upgrade {0} to 3.5&amp;quot;&lt;/span&gt;, proj.Name)
   &lt;span style="color: #0000ff"&gt;End&lt;/span&gt; &lt;span style="color: #0000ff"&gt;Try&lt;/span&gt;

&lt;span style="color: #0000ff"&gt;Next&lt;/span&gt; proj&lt;/pre&gt;
&lt;/div&gt;

&lt;p&gt;Why 196613, you ask? Well, when I see such a number my first instinct is to feed it into calc.exe and switch it to hexadecimal. And I was right: 196613 in decimal converts to 0x00030005 - You can see the framework version hiding in there. Major version in the high word, minor in the low word. The previous TargetFramework number was 131072 - 0x00020000, or 2.0.&lt;/p&gt;

&lt;p&gt;&amp;#160;&lt;/p&gt;

&lt;p&gt;(Nitpickers might point out that I could simply set it to &amp;amp;30005 rather than messing with the obscure decimal number. They would be correct - but I got to this number through the debugger, so that's how it will stay)&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=6219753" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/avnerk/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/CodeSnippets/default.aspx">CodeSnippets</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2B002B002F00_CLI/default.aspx">C++/CLI</category></item><item><title>Another minor C#/C++ difference - adding existing files</title><link>http://weblogs.asp.net/avnerk/archive/2007/10/28/another-minor-c-c-difference-adding-existing-files.aspx</link><pubDate>Sun, 28 Oct 2007 14:35:24 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:4801261</guid><dc:creator>Avner Kashtan</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/avnerk/rsscomments.aspx?PostID=4801261</wfw:commentRss><comments>http://weblogs.asp.net/avnerk/archive/2007/10/28/another-minor-c-c-difference-adding-existing-files.aspx#comments</comments><description>&lt;p&gt;Another minor detail that bit me for a few minutes today. I'm posting this so I'll see it and remember, and possibly lodge it in other people's consciousness.&lt;/p&gt; &lt;p&gt;Using Visual Studio 2005, adding an existing .cs file to a C# project will cause a copy of that file to be created in the project directory. If I want to link to the original file, I need to explicitly choose Add As Link from the dropdown on the Add button. &lt;/p&gt; &lt;p&gt;C++ projects, however, have the opposite behavior. Adding an existing item in a different folder will add a link to the original file in the original location. To create a copy, manually copy it to the project dir.&lt;/p&gt; &lt;p&gt;That is all.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=4801261" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/avnerk/archive/tags/Visual+Studio/default.aspx">Visual Studio</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2B002B002F00_CLI/default.aspx">C++/CLI</category></item><item><title>Unmanaged deployment is a true DLL Hell</title><link>http://weblogs.asp.net/avnerk/archive/2007/08/30/unmanaged-deployment-is-a-true-dll-hell.aspx</link><pubDate>Wed, 29 Aug 2007 23:16:07 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:3660179</guid><dc:creator>Avner Kashtan</dc:creator><slash:comments>1</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/avnerk/rsscomments.aspx?PostID=3660179</wfw:commentRss><comments>http://weblogs.asp.net/avnerk/archive/2007/08/30/unmanaged-deployment-is-a-true-dll-hell.aspx#comments</comments><description>&lt;p&gt;By a staggering margin, most of my problems integrating&amp;nbsp;C++/CLI code into my C#-based project has been deployment problems. Without fail, every integration or test deployment will be plagued with inexplicable problems. I'll try to list a few, with their causes and (probable) solutions:&lt;/p&gt; &lt;p&gt;1) .NET assemblies are usually very loose in what they'll bind to. If I compiled A.DLL against B.DLL version 1.0.0.0, it will still work if it can only find B.DLL version 1.2.0.0. I don't have to rebuild and reversion everything every time. However, if my C# A.DLL has a reference to my CPPCLI.DLL v1.0.0.0, and I then put CPPCLI.DLL v1.1.0.0, I'll get an exception saying the referenced DLL wasn't found. Annoying.&lt;/p&gt; &lt;p&gt;Solution: If you're changing the version number of a C++/CLI assembly, make sure to recompile any assembly that references it.&lt;/p&gt; &lt;p&gt;2) C++/CLI can be compiled as a pure .NET assembly, just like C# or VB. I don't really see the point in that, unless I'm a C++ coder and refuse to switch syntax. There isn't a great deal of benefit to that over writing in C#, because I can't reference unmanaged code easily. The standard mode, /clr, allows me to mix both managed and unmanaged code. The problem is that a mixed-mode assembly has a dependency on the Visual C++ Runtime libraries. This means that if the machine I am installing on doesn't have it, I'll crash. Furthermore, if I developed my code on a machine running VS2005SP1, my MSVCRT version will be 8.0.50727.762, but on a machine with vanilla .NET2.0 and the corresponding runtimes, I'll just find 8.0.50727.42. Result? An inexplicable "FileNotFoundException", not saying what's missing.&lt;/p&gt; &lt;p&gt;Solution: Make sure your deployment scenario includes installing the relevant MSVC++ Runtime. VS2005 comes with a Merge Module (msm) so you can add it to any MSI project.&lt;/p&gt; &lt;p&gt;3) The usual reason to add C++/CLI code to a C# project is to act as a bridge to an unmanaged API. Usually this API is composed of various DLLs. These DLLs can come in many forms - some are statically linked to their respective runtimes, some link dynamically. Some expect other DLLs in the same directory, others expect them in the PATH. Many times we'll get cryptic Module Load Failed errors or FileLoadFailedExceptions. &lt;/p&gt; &lt;p&gt;One tool we have for this is Filemon and Procmon, SysInternals' wonderful debugging tools. Open them up, add a filter to weed out the noise and see what files receive a FILE_NOT_FOUND error. &lt;/p&gt; &lt;p&gt;Another indispensible tool is the Dependency Walker (depends.exe) that is shipped with Visual Studio (C:\Program Files\Microsoft Visual Studio 8\Common7\Tools\Bin). This tool will show you all the DLLs that our file has a dependency on. First thing to look for is any dependencies highlighted in red, underneath the tree. These are our missing buddies. Ignore anything that has a little hourglass next to it - these are delay-load modules and probably not the source of the problem. &lt;/p&gt; &lt;p&gt;One thing to note when opening our C++/CLI DLLs in Depends is the dependencies on the MSVC++ Runtime. Look for a dependency on "MSVCP80.DLL". You might find instead "MSVCP80D.DLL" - this means that we're bound to the Debug build of the runtime, which probably doesn't exist on our servers. This usually means that we've compiled the project in DEBUG build, rather than RELEASE. &lt;/p&gt; &lt;p&gt;One last indispensible tool is trusty old Reflector. Open our managed A.DLL that contains a reference to CPPCLI.DLL, and we can see what version it was referenced against. This can help us find problems like I mentioned in section 1.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;There, that's all I can think of at the moment. Hope it gets some googlejuice and helps someone stuck as I am.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=3660179" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/avnerk/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2B002B002F00_CLI/default.aspx">C++/CLI</category></item><item><title>More Tales from the Unmanaged Side - System.String -&gt; char*</title><link>http://weblogs.asp.net/avnerk/archive/2007/08/28/more-tales-from-the-unmanaged-side-system-string-gt-char.aspx</link><pubDate>Tue, 28 Aug 2007 16:08:50 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:3646045</guid><dc:creator>Avner Kashtan</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/avnerk/rsscomments.aspx?PostID=3646045</wfw:commentRss><comments>http://weblogs.asp.net/avnerk/archive/2007/08/28/more-tales-from-the-unmanaged-side-system-string-gt-char.aspx#comments</comments><description>&lt;p&gt;Today,&amp;nbsp;I had a very tight deadline to achieve a very simple task: pass a managed .NET string to an API function that expects a null-terminated char*. Trivial, you would expect? Unfortunately it wasn't.&lt;/p&gt; &lt;p&gt;My first though was to do the pinning trick that I mentioned in my last post, but in this case I needed my resulting char* to be null-terminated.&lt;/p&gt; &lt;p&gt;Second thought was to go to the System.Runtime.InteropServices.Marshal class and see what it had for me. I found two contenders:&lt;/p&gt; &lt;p&gt;1) Marshal::StringToBSTR() - this creates a COM-compatible BSTR. I found various tutorials about BSTRs saying that they MIGHT be, under SOME circumstances, compatibles with zero-terminated wide-character strings. Didn't seem to be safe enough.&lt;/p&gt; &lt;p&gt;2) Marshal::StringToHGlobalAuto() - this allocates a block of memory, copies the characters in and even null-terminates it for me. This looked like a winner. Stage one was done - we managed to get an unmanaged string. But can we use it now?&lt;/p&gt; &lt;p&gt;The next problem was that StringToHGlobalAuto returns an IntPtr, and&amp;nbsp;casting it to a char* led to a compilation error. The solution to that is either to cast the IntPtr to a (void*) before casting to (char*), or to do the same action by calling the IntPtr's ToPointer() method. The second option seems neater to those of us who like as few direct casts as possible - I'd rather my conversion was done by a method than by a possibly unsafe casting operation. I'm sure those more concerned with method-call overheads will disagree.&lt;/p&gt; &lt;p&gt;The next problem is that the result of this operation was a single character string - the first character from the expected string. C++ programmers who've struggled with Unicode will quickly spot the problem.&lt;/p&gt; &lt;p&gt;char* strings are null terminated - the first byte containing 00 is the terminator. For Unicode strings as returned by StringToHGlobal&lt;strong&gt;Auto&lt;/strong&gt;, each character takes 2 bytes. If it's a character from the lower reaches of the Unicode spectrum, the second byte, being the high-order byte, will usually be 00, thus terminating the string. There are two options:&lt;/p&gt; &lt;p&gt;1. Instead of char*, use wchar_t* - wide, 2-byte character string, terminated by two null bytes.&lt;br&gt;2. use StringToHGlobal&lt;strong&gt;ANSI&lt;/strong&gt;, which converts the string to standard 8-bit ANSI encoding. This should be used only if we know we can't receive any unicode characters, or (as in my case) when the API we call only acceptts char*. :(&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;So that's a bit more C++ that haunted and taunted me today. See you next time.&lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=3646045" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/avnerk/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2B002B002F00_CLI/default.aspx">C++/CLI</category></item><item><title>A C# coder in a C++/CLI world, part 1</title><link>http://weblogs.asp.net/avnerk/archive/2007/08/28/a-c-coder-in-a-c-cli-world-part-1.aspx</link><pubDate>Tue, 28 Aug 2007 13:48:50 GMT</pubDate><guid isPermaLink="false">c06e2b9d-981a-45b4-a55f-ab0d8bbfdc1c:3644918</guid><dc:creator>Avner Kashtan</dc:creator><slash:comments>3</slash:comments><wfw:commentRss xmlns:wfw="http://wellformedweb.org/CommentAPI/">http://weblogs.asp.net/avnerk/rsscomments.aspx?PostID=3644918</wfw:commentRss><comments>http://weblogs.asp.net/avnerk/archive/2007/08/28/a-c-coder-in-a-c-cli-world-part-1.aspx#comments</comments><description>&lt;p&gt;Recently I've found myself stumbling around some C++/CLI code. C++ is a language which I learned years ago and never really worked with seriously, so I've been cursing and moaning as I worked. Strange for me to go back to a (partially) unmanaged environment now, with all sorts of assumptions that I have proven to be false. I'll try to go over some pitfalls and insights I'm having during the visit. This is the first:&lt;/p&gt; &lt;p&gt;The Garbage Collector really spoiled me. I'm not talking about deleting what I instantiated, but all sorts of subtler bugs related to going out of scope. For instance, I had code like this that receives a managed, .NET byte[] and turns it into an unmanaged char*:&lt;/p&gt; &lt;p&gt;&lt;font face="courier new"&gt;void DoSomething(array&amp;lt;Byte&amp;gt;^ data)&lt;br&gt;{&lt;/font&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;br&gt;&amp;nbsp;&amp;nbsp; // Pin the managed array to an unmanaged char*.&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;pin_ptr&amp;lt;Byte&amp;gt; pinnedBuffer = &amp;amp;data[0];&lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;char* buffer = (char*)pinnedBuffer;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/font&gt;&lt;/p&gt; &lt;p&gt;&lt;font face="courier new"&gt;&amp;nbsp;&amp;nbsp; // Now do something with the unmanaged buffer.&lt;br&gt;}&lt;/font&gt;&lt;/p&gt; &lt;p&gt;Simple enough, but then I found myself needing it in a different method too. My first instinct, of course, is refactor those two lines into a new method to do the array conversion, especially since I had a couple of lines of parameter validation there too. But my new GetUnmanagedBuffer(array&amp;lt;Byte&amp;gt;^) method wasn't as simple as I hoped. This is because the pinnedBuffer object that I created to prevent the GC from moving the managed array went out of scope when the method exited, and by the time I used the buffer in my unmanaged code, the data wasn't sure to be there anymore.&lt;/p&gt; &lt;p&gt;In the managed world, we're used to one of two scenarios when returning function parameters: either's a value type that's copied completely, or a reference type that passes a managed, GCed reference. In both these cases, we know that returning any object from a method is a safe operation. &lt;/p&gt; &lt;p&gt;Additonally, we in managed land are used to refactoring being a safe operation, in most cases. If I don't have to worry about scope, I don't worry about extracting any block of code into its own method. In C++, however, I have this constant uncertainty. It will pass with exprience, but I still feel much less safe than I would moving to a different, managed environment.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;This was the first installment of Tales from the Unmanaged Side. I'll see if I have anything else to say the more I work on this &lt;/p&gt;&lt;img src="http://weblogs.asp.net/aggbug.aspx?PostID=3644918" width="1" height="1"&gt;</description><category domain="http://weblogs.asp.net/avnerk/archive/tags/.NET/default.aspx">.NET</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://weblogs.asp.net/avnerk/archive/tags/C_2B002B002F00_CLI/default.aspx">C++/CLI</category></item></channel></rss>