tags:

views:

217

answers:

2

I am writing a c# app using .NET 2.0. I need to use an old library for proprietary compression. I don't have source code for the library, and the developers behind it are long gone.

My problem is that the resulting char[] contains nulls, and is being truncated. Here is the declaration for the function:

[DLLImport("foo.dll")]
public static extern bool CompressString(char[] inputValue, out char[] outputValue, uint inputLength, out uint outputLength);

How can I declare that the output char[] should be handled as a byte[], and not null terminated?


More info:

I do have the header file. Here is the declaration:

BOOL CompressString(char *DecompBuff, char **RetBuff, unsigned long DecompLen, unsigned long *RetCompLen);
+3  A: 

Have a look at the MSDN article for passing arrays in P/Invoke. I think that you may want to use the SizeParamIndex to tell the marshaller which argument holds the size of the array passed along.

Edit: SizeParamIndex is unfortunately not allowed on out and ref parameters. You could, however, copy it manually:

[DLLImport("foo.dll")]
public static extern bool CompressString([MarshalAs(UnmanagedType.LPArray, SizeParamIndex=2)] char[] inputValue, out IntPtr outputValue, uint inputLength, out uint outputLength);

public static bool CompressStringInvoke(char[] inputValue, out char[] outputValue, uint inputLength) {
 IntPtr outputPtr;
 uint outputLen;
 if (CompressString(inputValue, out outputPtr, inputLength, out outputLen)) {
  outputValue = new char[outputLen];
  Marshal.Copy(outputPtr, outputValue, 0, (int)outputLen);
  return true;
 }
              outputValue = new char[0];
 return false;
}
Lucero
I get this error: Cannot marshal 'parameter #2': Cannot use SizeParamIndex for ByRef array parameters.
Jon B
Right. Edited with an alternate solution.
Lucero
Brilliant! Thanks! (I fixed a couple of minor syntax issues)
Jon B
`Marshal.Copy` will copy bytes, not chars. In general, it seems that this needs `byte` everywhere there is `char` currently.
Pavel Minaev
@Jon: thanks!@Pavel: no, it's the number of elements according to the documentation. Since this uses the `char[]` overload, that should be fine, if the C-char is 16-bit.
Lucero
A: 

Pinvoke.Net should provide you some hints on declaring your method signature

Raj