title: Determining DLLImport arguments and safely calling an unmanaged C function
body: <p>As a follow-up to my previous question, I finally got the C dll exported and usable in C#, but I'm stuck trying to figure out the proper argument types and calling method.  </p>
  
  <p>I've researched here on SO but there doesn't seem to be a pattern to how variable types are assigned.  </p>
  
  <p>I see some people suggest a <code>StringBuilder</code> for <code>uchar*</code>, others a <code>byte[]</code>, some references to 'unsafe' code, etc.  <strong>Can anyone recommend a solution based on this specific use-case?</strong>  </p>
  
  <p>Also note the exception generated as the code stands now, right after the call to the C function.</p>
  
  <p>C function import:</p>
  
  <pre><code>[DllImport("LZFuncs.dll")]
  internal static extern long LZDecomp(ref IntPtr outputBuffer, byte[] compressedBuffer, UInt32 compBufferLength); //Originally two uchar*, return is size of uncompressed data.
  </code></pre>
  
  <p>C function signature:</p>
  
  <pre><code>long LZDecomp(unsigned char *OutputBuffer, unsigned char *CompressedBuffer, unsigned long CompBufferLength)
  </code></pre>
  
  <p>Used as below:</p>
  
  <pre><code>for (int dataNum = 0; dataNum &lt; _numEntries; dataNum++)
          {
              br.BaseStream.Position = _dataSizes[dataNum]; //Return to start of data.
              if (_compressedFlags[dataNum] == 1)
              {
                  _uncompressedSize = br.ReadInt32();
                  byte[] compData = br.ReadBytes(_dataSizes[dataNum] - 4);
                  IntPtr outData = IntPtr.Zero;
                  LZFuncs.LZDecomp(ref outData, compData, Convert.ToUInt32(compData.Length));
                  var uncompData = new byte[_uncompressedSize]; //System.ExecutionEngineException was unhandled
                  Marshal.Copy(outData, uncompData, 0, Convert.ToInt32(_uncompressedSize));
                  BinaryWriter bw = new BinaryWriter(new FileStream("compData" + dataNum + ".txt", FileMode.CreateNew));
                  bw.Write(uncompData);
                  bw.Close();
              }
              else
              {
                  BinaryWriter bw = new BinaryWriter(new FileStream("uncompData" + dataNum + ".txt", FileMode.CreateNew));
                  bw.Write(br.ReadBytes(_dataSizes[dataNum]));
                  bw.Close();
              }
          }
  </code></pre>
  
  <p>I assume the C code is clobbering the memory pretty severely if it's breaking the C# caller with a CLR exception like that, but due to how the C code is written, there's absolutely no way to modify it without breaking the functionality, it's effectively a black box. (Written in assembly, for the most part.)</p>
  
  <p>For reference, just a few questions I've read over in an effort to solve this myself:</p>
  
  <p><a href="https://stackoverflow.com/questions/14633338/how-do-i-return-a-byte-array-from-c-to-c-sharp">How do I return a byte array from C++ to C#</a></p>
  
  <p><a href="https://stackoverflow.com/questions/13123151/correct-way-to-marshall-uchar-from-native-dll-to-byte-in-c-sharp?lq=1">Correct way to marshall uchar[] from native dll to byte[] in c#</a></p>
  
  <p>There have been others but those are the most recent.</p>