0

How can I read the error string in C# from this C++ dll call?

//
//  PARAMETERS:
//      objptr
//          Pointer to class instance.
//
//      pBuffer
//          Pointer to buffer receiving NULL terminated error message string.   
//          If this value is zero, the function returns the required buffer size, in bytes,
//          and makes no use of the pBuffer. 
//
//      nSize
//          Size of receiving buffer.
//          If this value is zero, the function returns the required buffer size, in bytes,
//          and makes no use of the pBuffer. 
//
//  RETURN VALUES:
//      If pBuffer or nSize is zero, the function returns the required buffer size, in bytes.
//      If the function succeeds, the return value is number of bytes copied into pBuffer.
//      If function fails return value is 0.
//
extern unsafe int GetError(uint objptr, byte* pBuffer, int nSize);

thanks!

Santiago Corredoira
  • 47,267
  • 10
  • 52
  • 56

3 Answers3

4

If you change the data type from byte* to IntPtr this might work:

Marshal.PtrToStringAnsi

Or one of the string constructors (one of them also includes an Encoding parameter):

String Constructors

Aviad P.
  • 32,036
  • 14
  • 103
  • 124
3
byte[] buffer = new byte[1000];
int size;
unsafe
{
  fixed ( byte* p = buffer )
  {
    size = GetError( ???, p, buffer.Length ); 
  }
}
string result = System.Text.Encoding.Default.GetString( buffer, 0, size );
Dan Byström
  • 9,067
  • 5
  • 38
  • 68
  • I used GetError(???, null, 0) to get the message size in order to create the buffer and worked also perfect. Thanks! – Santiago Corredoira Dec 27 '09 at 11:42
  • You could also try to change byte* to StringBuilder and pass that instead and avoid the unsafe code. – Mikael Svenson Dec 27 '09 at 12:06
  • @Mikael: how can I do it? The dll method expects byte* – Santiago Corredoira Dec 27 '09 at 15:44
  • @Dawkins: what the method really expects is a 32 bit pointer. What it points to doesn't really matter as long as it points to something that it can write to without causing a protection fault. Using a StringBuilder will work, just as Mikael says - as long as you remember to allocate sufficient memory in the StringBuilder. Since your question specifically stated a byte* and unsafe code - I just went down that road in my answer. There exists quite a few more possible solutions. – Dan Byström Dec 27 '09 at 18:26
  • thanks danbystrom, but how should I pass the Stringbuilder? The compiler throws an exception if I just replace the byte* with it. – Santiago Corredoira Dec 28 '09 at 11:38
  • It should not. Not if you change the declaration and then pass it a StringBuilder. – Dan Byström Dec 28 '09 at 13:11
0

Marshal.AllocHGlobal(int) plus Marshal.PtrToStringAuto(IntPtr, int) perhaps?

Some code context would be nice, as I'm assuming that you're already coercing byte* into an IntPtr using p/invoke or some other trickery.

Basically, call your function to get the buffer size, allocate a buffer using AllocHGlobal(), call it again, read the string in, then free the buffer (using Marshall.FreeHGlobal(IntPtr)). This is assuming you can use Marshall's allocator, of course.

Kevin Montrose
  • 22,191
  • 9
  • 88
  • 137