Trivial P/Invoke question

L

Larry Smith

Hi there,

I need to initialize the first character to (binary) zero in a buffer
returned via "Marshal.AllocCoTaskMem()". This is ultimately going to be
assigned to an LPTSTR pointer inside a Win32 structure (for subsequent
passing to a Win32 function). Can someone show me how to actually assign
this zero (C null terminator) from the "IntPtr" returned from the latter
function (with emphasis on the fact that I'm dealing with a TCHAR from
Win32 - could be one or two characters that need to be zeroed IOW) . Thanks.
 
M

Mattias Sjögren

Larry,
This is ultimately going to be
assigned to an LPTSTR pointer inside a Win32 structure (for subsequent
passing to a Win32 function).

In that case, wouldn't it be easier to use a string?

Can someone show me how to actually assign
this zero (C null terminator) from the "IntPtr" returned from the latter
function (with emphasis on the fact that I'm dealing with a TCHAR from
Win32 - could be one or two characters that need to be zeroed IOW) . Thanks.

If you know that the buffer is always at least two bytes large, the
easiest way is

Marshal.WriteInt16(ptr, 0);


Mattias
 
L

Larry Smith

Thanks for the feedback.
Larry,


In that case, wouldn't it be easier to use a string?

Yes but can you. I downloaded some sample code from a MSFT developer who
relies on low-level techniques for this. He seems to imply by one of his
comments that you need to rely on low-level methods. I'd much rather rely on
"string" of course but how?
If you know that the buffer is always at least two bytes large, the
easiest way is

Marshal.WriteInt16(ptr, 0);

Ok, but in theory I don't know if it will always be two bytes. I can't
assume an integer either (2 bytes or otherwise). While it will work for
Unicode on Win32, tt's really the OS's native "char" I need to work with
(whatever its size is) so a neutral way is required. If you have a Win32
background then it's whatever TCHAR natively maps to..
 
M

Mattias Sjögren

Yes but can you. I downloaded some sample code from a MSFT developer who
relies on low-level techniques for this. He seems to imply by one of his
comments that you need to rely on low-level methods. I'd much rather rely on
"string" of course but how?

It doesn't always work, but you can easily try it simply by changing
the field type from IntPtr to string.

Ok, but in theory I don't know if it will always be two bytes. I can't
assume an integer either (2 bytes or otherwise). While it will work for
Unicode on Win32, tt's really the OS's native "char" I need to work with
(whatever its size is) so a neutral way is required. If you have a Win32
background then it's whatever TCHAR natively maps to..

Well sizeof(TCHAR) can only be one or two bytes on all current
platforms that I know of, so by always writing two bytes you ensure
that at least as many bytes as needed are zeroed out.

But you can certainly take the native char size into account if you
want.

if (Marshal.SystemDefaultCharSize == 1)
Marshal.WriteByte(ptr, 0);
else
Marshal.WriteInt16(ptr, 0);

of if you want to be really dynamic

byte[] zeros = new byte[Marshal.SystemDefaultCharSize];
Marshal.Copy(zeros, 0, ptr, zeros.Length);


Mattias
 
L

Larry Smith

Yes but can you. I downloaded some sample code from a MSFT developer who
relies on low-level techniques for this. He seems to imply by one of his
comments that you need to rely on low-level methods. I'd much rather rely
on
"string" of course but how?

It doesn't always work, but you can easily try it simply by changing
the field type from IntPtr to string.

Ok, but in theory I don't know if it will always be two bytes. I can't
assume an integer either (2 bytes or otherwise). While it will work for
Unicode on Win32, tt's really the OS's native "char" I need to work with
(whatever its size is) so a neutral way is required. If you have a Win32
background then it's whatever TCHAR natively maps to..

Well sizeof(TCHAR) can only be one or two bytes on all current
platforms that I know of, so by always writing two bytes you ensure
that at least as many bytes as needed are zeroed out.

But you can certainly take the native char size into account if you
want.

if (Marshal.SystemDefaultCharSize == 1)
Marshal.WriteByte(ptr, 0);
else
Marshal.WriteInt16(ptr, 0);

of if you want to be really dynamic

byte[] zeros = new byte[Marshal.SystemDefaultCharSize];
Marshal.Copy(zeros, 0, ptr, zeros.Length);


Mattias

Ok, thanks for the help. After severals hours of research/experimentation I
think I finally have it figured out now. Your reference to
"Marshal.SystemDefaultCharSize" solves the last piece of the puzzle. Thanks
again.
 

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