title: C# Char* to String
body: <p>I've looked around a lot and can't seem to find a solution to anything similar to what I'm doing. I have two applications, a native C++ app and a managed C# app. The C++ app allocates a pool of bytes that are used in a memory manager. Each object allocated in this memory manager has a header, and each header has a char* that points to a name given to the object. The C# app acts as a viewer for this memory. I use memory mapped files to allow the C# app to read the memory while the C++ app is running. My issue is that I am trying to read the name of the object from the header structure and display it in C# (or just store it in a String, whatever). Using unsafe code I am able to convert the four bytes that make up the <code>char*</code> into an <code>IntPtr</code>, convert that to a <code>void*</code>, and call <code>Marshal.PtrToStringAnsi</code>. This is the code:</p>
  
  <pre><code>IntPtr namePtr = new IntrPtr(BitConverter.ToInt32(bytes, index));
  unsafe
  {
      void* ptr = namePtr.ToPointer();
      char* cptr = (char*)ptr;
      output = Marshal.PtrToStringAnsi((IntPtr)ptr);
  }
  </code></pre>
  
  <p>In this case, <code>bytes</code> is the array read from the memory mapped file that represents all of the pool of bytes created by the native app, and <code>index</code> is the index of the first byte of the name pointer.</p>
  
  <p>I have verified that, on the managed side of things, the address returned by the call to <code>namePtr.ToPointer()</code> is exactly the address of the name pointer in the native app. If this were native code, I would simply cast <code>ptr</code> to a <code>char*</code> and it would be fine, but in managed code I've read I must use the Marshaller to do this.</p>
  
  <p>This code yields varying results. Sometimes <code>cptr</code> is null, sometimes it points to <code>\0</code>, and other times it points to a few Asian characters (which when run through the <code>PtrToStringAnsi</code> method produce seemingly irrelevant characters). I thought it might be a <code>fixed</code> thing, but <code>ToPointer</code> produces a fixed pointer. And sometimes after the cast to a <code>char*</code> the debugger says <code>Unable to evaluate the expression. The pointer is not valid</code> or something like that (it's not easy to repro every varying thing that comes back). And other times I get an access violation when reading the memory, which leads me to the C++ side of things.</p>
  
  <p>On the C++ side, I figured there might be some issues with actually reading the memory because although the memory that stores the pointer is part of the memory mapped file the actual bytes that make up the text are not. So I looked at how to change read/write access to memory (on Windows, mind you) and found the VirtualProtect method in the Windows libraries, which I use to change access to the memory to PAGE_EXECUTE_WRITECOPY, which I figured would give any application that has a pointer to that address will be able to at least read what's there. But that didn't solve the issue either.</p>
  
  <p>To put it shortly:</p>
  
  <p><strong>I have a pointer (in C#) to the first char in a char array (that was allocated in a C++ app) and am trying to read that array of char's into a string in C#.</strong></p>
  
  <p>EDIT:</p>
  
  <p>The source header looks like this:</p>
  
  <pre><code>struct AllocatorHeader
  {
  // These bytes are reserved, and their purposes may change.
  char _reserved[4];
  
  // A pointer to a destructor mapping that is associated with this object.
  DestructorMappingBase* _destructor;
  
  // The size of the object this header is for.
  unsigned int _size;
  
  char* _name;
  };
  </code></pre>
  
  <p>The <code>_name</code> field is the one I'm trying to dereference in C#.</p>
  
  <p>EDIT:</p>
  
  <p>As of now, even using the solutions provided below, I am unable to dereference this char* in managed code. As such, I have simply made a copy of the char* in the pool referenced by the memory mapped file and use a pointer to that. This works, which makes me believe this is a protection-related issue. If I find a way to circumvent this at some point, I will answer my own question. Until then, this will be my workaround. Thanks to all who helped!</p>