views:

641

answers:

1

I have the following method defined:

internal string GetInformation(string recordInformation)
{
    int bufferSize = GetBufferSize(recordInformation);

    string outputRecord;
    IntPtr output = Marshal.AllocHGlobal(bufferSize);

    try
    {
     _returnCode = UnmanagedMethod(recordInformation, output, recordInformation.Length);
     byte[] outputData = new byte[bufferSize];
     Marshal.Copy(output, outputData, 0, bufferSize);
     outputRecord = ASCIIEncoding.ASCII.GetString(outputData, 0, bufferSize);
    }
    finally
    {
     Marshal.FreeHGlobal(output);
    }

    return outputRecord;
}

In this method, a provided string (recordInformation) is passed to a method written in C (UnmanagedMethod). Based on the documentation I have for this method, the bufferSize is setup properly; however, Marshal.Copy creates an array the size of recordInformation.Length instead. When I assigned the ray to the outputRecord variable, the content of the string is the length of the bufferSize; however, there is a number of NUL (Char 0) to fill the remainder of the string until it hits the recordInformation.Length field. If I change the last parameter in the UnmanagedMethod parameter list to bufferSize, the output string turns into nothing but NUL characters.

Am I doing the marshaling wrong or is there a way after the string has been created from the byte array to remove the NUL characters?

Thanks

+1  A: 

I don't see anything wrong with your example.

You'll probably want to note that .NET strings can contain NUL/NULL characters- but really, characters that just have the value 0 ('\0' or '\x00').

You can scrub out the characters by doing a replace or walking over the string and keep everything before the first NUL. Most likely you will want the latter, as this is typical for zero-terminated strings in C.

Here's a quick example (Console) that illustrates what will happen in either case.

string sTest1 = "abc\0\0def";

string sTest2 = sTest1.Replace("\0", "");
Console.WriteLine(sTest2);

int iLocation = sTest1.IndexOf('\0');
string sTest3 = "";
if (iLocation >= 0)
{
    sTest3 = sTest1.Substring(0, iLocation);
}
else
{
    sTest3 = sTest1;
}
Console.WriteLine(sTest3);

Console.ReadLine();

The former will result in abcdef, and the latter will result in abc.

Also note that the latter method will require you to check for NUL characters first, just in case the string contains the entire buffer location and there were no NUL characters at all.

meklarian
I should add that you could also just scan the outputData buffer for the first byte equal to zero to truncate the string, too.
meklarian
I attempted to do the Replace("\0", "") at the end of the method and I still am getting the NUL characters in the string I'm returning in the method.
JamesEggers
did you return the result of the call? ex. [return outputRecord.Replace("\0","");]. string's Replace() returns a new string and doesn't modify the original string.
meklarian
Yea I did that. I looked a little bit deeper in terms of the string while debugging and some of what I'm doing with the returned string. I'm writing the returned string to a text file. The text file when viewed in Notepad++ or wordpad has the NUL characters; however, the string inside of the code does not. Very odd but should be ok going forward from what I can tell.
JamesEggers