Pinvoke question: importing char* returning functions.

B

Beorne

I have to call a c++ library funtion returning a string with the
following signature:
char *get_identifier();

Usually when I have to marshal a function with a char* output
parameter I do:
[DllImport("library.dll", CharSet = CharSet.Ansi,)]
static extern int get_identifier2([MarshalAs(UnmanagedType.LPStr)]
StringBuilder Ack_Msg, int msg_len);

But in this case the char* string is returned as output.
I've tried
[DllImport("library.dll", CharSet = CharSet.Ansi,)]
static extern [MarshalAs(UnmanagedType.LPStr)] StringBuilder
get_identifier();
but this does throw an error.

How I could do to state explicitly that the returning char string is
an ansi (LPStr) string?

And how could I find the size of the returned string?

Thanks.
 
B

Ben Voigt [C++ MVP]

Beorne said:
I have to call a c++ library funtion returning a string with the
following signature:
char *get_identifier();

Usually when I have to marshal a function with a char* output
parameter I do:
[DllImport("library.dll", CharSet = CharSet.Ansi,)]
static extern int get_identifier2([MarshalAs(UnmanagedType.LPStr)]
StringBuilder Ack_Msg, int msg_len);

But in this case the char* string is returned as output.
I've tried
[DllImport("library.dll", CharSet = CharSet.Ansi,)]
static extern [MarshalAs(UnmanagedType.LPStr)] StringBuilder
get_identifier();
but this does throw an error.

You have to specify [return: ...] in your attribute I believe, but continue
reading.
How I could do to state explicitly that the returning char string is
an ansi (LPStr) string?

IMO, you *must* use pointers to deal with this. My preference is C++/CLI of
course, but C# should work too. Declare the return value as an IntPtr, use
the Marshal class to retrieve your data. P/invoke's built-in marshalling
won't work, because it doesn't give you access to the pointer, which you
need to pass to the appropriate deallocation function after you are done
using it.
And how could I find the size of the returned string?

lstrlen, from kernel32.dll, for example
http://www.pinvoke.net/default.aspx/kernel32/lstrlen.html
 
W

Willy Denoyette [MVP]

Beorne said:
I have to call a c++ library funtion returning a string with the
following signature:
char *get_identifier();

Usually when I have to marshal a function with a char* output
parameter I do:
[DllImport("library.dll", CharSet = CharSet.Ansi,)]
static extern int get_identifier2([MarshalAs(UnmanagedType.LPStr)]
StringBuilder Ack_Msg, int msg_len);

But in this case the char* string is returned as output.
I've tried
[DllImport("library.dll", CharSet = CharSet.Ansi,)]
static extern [MarshalAs(UnmanagedType.LPStr)] StringBuilder
get_identifier();
but this does throw an error.

How I could do to state explicitly that the returning char string is
an ansi (LPStr) string?

And how could I find the size of the returned string?

Thanks.



Declare the return type as IntPtr in C#.
The char* must point to a 'null' terminated char sequence, so there is no
need to know the length, the interop layer will copy the char array up to
and possibly including the terminating 'null' character when marshaling.
You have to pass the returned pointer to Marshal.PtrToStringAnsi in order to
marshal the char array to a managed string.

IntPtr ptr = F();
string s = Marshal.PtrToStringAnsi(ptr);

Willy.
 

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