Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / .NET Framework / Interop / July 2004

Tip: Looking for answers? Try searching our database.

Understanding Marshal when a string is to be returned from the API

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Just Me - 30 Jul 2004 16:29 GMT
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.

The following does work.

1) I'd like to kinow me why String works in this case.
Since String can't be changed I thought StringBuilder should be used
since I'm looking for a return in that variable.
I believe that's what the Doc says to do (for a fixed length string at
least).

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!

3)Instead of using the "W" version would it still work if you used the "A"
version?

4)How about "Auto"?

Thanks in advance

> <DllImport("shell32.dll", entrypoint:="SHGetFolderPathW", _
>
> CallingConvention:=CallingConvention.StdCall)> _
>
> Private Shared Function SHGetFolderPath(ByVal hWnd As Integer, _
>
> ByVal nFolder As Integer, ByVal nToken As Integer, _
>
> ByVal dwFlags As Integer, _
>
> <MarshalAs(UnmanagedType.LPTStr)> ByVal lpszPath As String) As Boolean
>
> End Function
>
> Dim strPath As String = Space(260)
>
> If SHGetFolderPath(0, CSIDL_CDBURN_AREA, 0, 0, strPath) = 0 Then
>
> strPath = strPath.Trim
>
> strPath = strPath.Substring(0, strPath.Length - 1)
>
> mstrBurnPath = strPath + "\"
>
> End If
BMermuys - 31 Jul 2004 02:04 GMT
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

Rate this thread:







Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.