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!

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

Comments

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 );

6 Comments

I used GetError(???, null, 0) to get the message size in order to create the buffer and worked also perfect. Thanks!
You could also try to change byte* to StringBuilder and pass that instead and avoid the unsafe code.
@Mikael: how can I do it? The dll method expects byte*
@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.
thanks danbystrom, but how should I pass the Stringbuilder? The compiler throws an exception if I just replace the byte* with it.
|
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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.