Hi,
> I've tried to get an answer to this before in a NG that usually answers
> so I'd guess it is not common knowledge.
[quoted text clipped - 6 lines]
> I believe that's what the Doc says to do (for a fixed length string at
> least).
Yes, you should.
> 2)How come the String is passed ByVal?
> I thought that meant to make a copy and pass a reference to that copy so
> your variable would never get changed!
String is a reference type.
Value types passed by value are always copied to the stack, changes cannot
be seen.
For reference types passed by value -or- value types passed by reference
there is still a difference between blittable and non-blittable types:
- Blittable types:
Have the same layout managed vs unmanaged and they don't need to be copied
instead they are pinned and a direct pointer is passed, so changes made by
unmanaged functions are visible as such. ([In,Out] by default)
- Non-blittable types:
Have a different layout managed vs unmanaged so they need to be marshalled
(some special copy), and by default it only happens in one direction [In] by
default. But you can force a copy-back if you specify [In,Out].
Back to your string issue. Because a managed string probely already
contains an array of wide chars, the framework for performance reasons,
considers strings as blittable when you want them to marshal as lpwstr. So
to optimize things, it passes a direct pointer to the string's internal
buffer. So the reason the string can be altered is a side-effect, the
framework can't protect it from changing because it passed a direct pointer.
You could almost get away with it, but there one catch, the null-terminator
used in c-style-strings, let me explain by example:
<example>
string t = new string ('a', 10);
// here a call to a unmanaged function with a string type as parameter
// which does: wcscpy (parameter1, L"test");
Console.WriteLine ( t ); // Prints "test\0aaaa" (note that \0 is shown
as a space)
Console.WriteLine ( t.Length ) ; // Prints 10
</example>
The framework has no idea why there is a null-terminator inside the string,
as far as it knows the string is still 10 chars of length.
A StringBuilder on the other hand is designed to be used in such a way.
First of all it has a capacity and a length. And the length will reflect
the effective size of the string (in our example this would be 4 not 10).
So it does know how to handle null-terminators placed by unmanaged
functions. And if you use sb.ToString() you will get to correct string with
the correct length.
Bottom line: Use a StringBuilder if the string must be modificable.
> 3)Instead of using the "W" version would it still work if you used the "A"
> version?
No, don't think so, because the framework will no longer see the string as a
blittable type, it will not pass a direct pointer, so the dll can't modify
it's internals.
> 4)How about "Auto"?
Auto is W or A depending on the platform (windows2000/windows98/etc)
HTH,
greetings
> Thanks in advance
>
[quoted text clipped - 23 lines]
> >
> > End If
Just Me - 31 Jul 2004 14:47 GMT
I've been trying to get an answer for some time.
It was worth the wait.
Much better explanation that anything in the Doc's
Only one thing: should // Prints "test\0aaaa"
be // Prints "test aaaaa"
5 "a"'s rather than 4?
Thanks much
> Hi,
>
[quoted text clipped - 107 lines]
> > >
> > > End If
BMermuys - 31 Jul 2004 18:33 GMT
Hi,
> I've been trying to get an answer for some time.
> It was worth the wait.
> Much better explanation that anything in the Doc's
I agree that the sdk information is not very detailed when it comes to
strings, information is also a little scattered around in different
articles.
> Only one thing: should // Prints "test\0aaaa"
> be // Prints "test aaaaa"
> 5 "a"'s rather than 4?
Yes, you're right, there should be 5 a's.
Greetings
> Thanks much
>
[quoted text clipped - 118 lines]
> > > >
> > > > End If
Just Me - 31 Jul 2004 20:28 GMT
thanks again
> Hi,
>
[quoted text clipped - 148 lines]
> > > > >
> > > > > End If