title: Receiving a char* from c++ into c#, and passing it back again
body: <p>I'm having memory leak issues with a third party c++ dll.  For certain calls, the dll allocates memory for the string, passes it out as a char* and then expects to receive that pointer back so that it can de-allocate the memory.</p>
  
  <p>Here are some comments from the header file, a couple of examples of where the char* get returned, and the signature of the "Release" method.</p>
  
  <p>(The dll is called SW_API, it's from a trade clearing house - if anyone has perhaps wrapped this already I'd love to talk to them!).</p>
  
  <pre><code>   /* Strings returned by the API are similarly normal nul-terminated C strings.
     * The user should not attempt to change any of the bytes or read past the
     * terminating nul of any returned string. All returned strings must be
     * released using SW_ReleaseString() once the user is finished with the
     * result. Failure to do this will result in memory leaks.
     */
  
      /**
       * @typedef const char* SW_XML
       * @brief A string containing an XML documents text.
       * @note As with all output strings, returned XML must be freed
       * by the user. See @ref resource.
       * @sa ErrorCodes
       */
      typedef const char* SW_XML;
  
      const char* STDAPICALLTYPE SW_GetLastErrorSpecifics();
  
      SW_ErrCode STDAPICALLTYPE SW_DealGetSWML(SW_LoginID           lh,
                                       const char*          swmlVersion,
                                       SW_DealVersionHandle dealVersionHandle,
                                       SW_XML*              resultXML_out);
  
  
      void STDAPICALLTYPE SW_ReleaseString(const char* buffer);
  </code></pre>
  
  <p>Attempting to read up from various sources, I have tried the following:</p>
  
  <pre><code>    // Extern declarations
      [DllImport(sw_api_dll, EntryPoint = "_SW_GetLastErrorSpecifics@0", CharSet = CharSet.Ansi)]
      public static extern IntPtr SW_GetLastErrorSpecifics();
  
      [DllImport(sw_api_dll, EntryPoint = "_SW_DealGetSWML@16", CharSet = CharSet.Ansi)]
      public static extern int SW_DealGetSWML(int lh, string swmlVersion, string dealVersionHandle, [Out] out IntPtr outputSWML);
  
      [DllImport(sw_api_dll, EntryPoint = "_SW_ReleaseString@4", CharSet=CharSet.Ansi)]
      public static extern void SW_ReleaseString(IntPtr buffer);
  
  
      // Using the externs.
      private static string GetIntPtrStringAndRelease(IntPtr ptr)
      {
          string result = Marshal.PtrToStringAnsi(ptr);
          API.SW_ReleaseString(ptr);
          return result;
      }
  
      public static int SW_DealGetSWML(int lh, string swmlVersion, string dealVersionHandle, ref string outputSWML)
      {
          IntPtr outputSWML_out = new IntPtr();
          int result = API.SW_DealGetSWML(lh, swmlVersion, dealVersionHandle, out outputSWML_out);
  
          outputSWML = GetIntPtrStringAndRelease(outputSWML_out);
  
          return result;
      }
  
      public static string SW_GetLastErrorSpecifics()
      {
          IntPtr ptr = API.SW_GetLastErrorSpecifics();
          return GetIntPtrStringAndRelease(ptr);
      }
  </code></pre>
  
  <p>It seems I just can't get the API to release the strings.</p>
  
  <p>Now, it's possible that this is just a bug in the API, but I doubt it.
  More likely is I'm doing something funamentally wrong.</p>
  
  <p>All I know is that my working set just keeps on growing.</p>
  
  <p>The company in question provide a Java wrapper but won't stretch to a .Net wrapper.</p>
  
  <p>Any help most gratefully received.</p>
  
  <p>Brett.</p>