Return string from C++

M

MRe

Hi,

I have a C++ function that takes an allocated char* array in, which it
will copy into, and return. I need to be able to access what was copied into
this array in a csharp program. So far I have this...

C++
void test(char* pOut)
{ CopyMemory(pOut, "abc", 3);
}

C#
[DllImport("test.dll", CharSet=CharSet.Auto)]
private static extern void test([MarshalAs(UnmanagedType.LPStr)] out string
Result);

public string RunTest()
{
StringBuilder sb = new StringBuilder(3, 3);
string Buffer;
// Create space in string - is there a better way to do this?
for(int Index = 0; Index < 3; Index++)
sb.Append(' ');
Buffer = sb.ToString();
test(out Buffer);
return Buffer;
}

But all I get is a System.NullReferenceException.

What's going on please?

Thank you,
Regards,
Eliott
 
J

Jon Shemitz

MRe said:
C++
void test(char* pOut)
{ CopyMemory(pOut, "abc", 3);
}

C#
[DllImport("test.dll", CharSet=CharSet.Auto)]
private static extern void test([MarshalAs(UnmanagedType.LPStr)] out string
Result);

public string RunTest()
{
StringBuilder sb = new StringBuilder(3, 3);
string Buffer;
for(int Index = 0; Index < 3; Index++)
sb.Append(' ');
Buffer = sb.ToString();
// Create space in string - is there a better way to do this?

Yes. string Buffer = new String(' ', 3);
test(out Buffer);
return Buffer;
}

But all I get is a System.NullReferenceException.

What's going on please?

My **guess** is that you want to pass the Buffer as a "ref", not an
"out".

(It might also have something to do with converting 16-byte char
strings to 8-byte char strings and back.)
 
W

Wessel Troost

void test(char* pOut)
{ CopyMemory(pOut, "abc", 3);
}
Depending on your implementation of CopyMemory, this may not append a zero
terminator for the string.
C#
[DllImport("test.dll", CharSet=CharSet.Auto)]
private static extern void test([MarshalAs(UnmanagedType.LPStr)] out
string
Result);
Instread of an "out" parameter, just pass a StringBuilder:

private static extern void test(
[MarshalAs(UnmanagedType.LPStr)] StringBuilder Result );
StringBuilder sb = new StringBuilder(3, 3);
string Buffer;
// Create space in string - is there a better way to do this?
for(int Index = 0; Index < 3; Index++)
sb.Append(' ');
Buffer = sb.ToString();

Since the DLL is not using the characters, there's no need to fill the
string with spaces. Just make sure there's enough capacity for the result
by replacing the above with:

StringBuilder sb = new StringBuilder(3);
test(out Buffer);

Now that we're using StringBuilder, the "out" modifier is no longer
required:

test(Buffer);
But all I get is a System.NullReferenceException.
There are many things in the code that might go wrong, but I don't see a
cause for NullReferenceException? Perhaps you can share the line of code
that raises the exception.

Greetings,
Wessel
 
R

Richard Blewett [DevelopMentor]

You should always use a StringBuilder to return strings from unmanaged code. .NET assumes strings are immutable and optimizes based on this. You should not allow unmanaged code to alter the contents of a string.

This is essentially the same issue as this

http://blogs.msdn.com/brada/archive/2004/06/03/148144.aspx

Regards

Richard Blewett - DevelopMentor
http://www.dotnetconsult.co.uk/weblog
http://www.dotnetconsult.co.uk
C++
void test(char* pOut)
{ CopyMemory(pOut, "abc", 3);
}

C#
[DllImport("test.dll", CharSet=CharSet.Auto)]
private static extern void test([MarshalAs(UnmanagedType.LPStr)] out string
Result);

public string RunTest()
{
StringBuilder sb = new StringBuilder(3, 3);
string Buffer;
for(int Index = 0; Index < 3; Index++)
sb.Append(' ');
Buffer = sb.ToString();
// Create space in string - is there a better way to do this?

Yes. string Buffer = new String(' ', 3);
test(out Buffer);
return Buffer;
}

But all I get is a System.NullReferenceException.

What's going on please?

My **guess** is that you want to pass the Buffer as a "ref", not an
"out".

(It might also have something to do with converting 16-byte char
strings to 8-byte char strings and back.)
 
M

MRe

Thank you all for your help - especially Wessel, your help was completely
hassle free (it's working now).
There are many things in the code that might go wrong, but I don't see a
cause for NullReferenceException? Perhaps you can share the line of code
that raises the exception.

The test being a simplified version of my problem, the actual code-line of
failure was

codaRead(m_hCoda, Id, Buffer, Length);

Only difference between this and the sample test; the Buffer size is
dynamic. The other three variables I know to be right and the C++ code works
when accessed by other languages. I guess it probably doesn't really matter
anyways, now that it's working with the StringBuilder.

Thank you again,
Regards,
Eliott
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top