Skip to content
This repository was archived by the owner on Nov 1, 2020. It is now read-only.

Implement Unicode and Ansi StringBuilder Marshalling#3315

Merged
shrah merged 2 commits intodotnet:masterfrom
shrah:null
Apr 26, 2017
Merged

Implement Unicode and Ansi StringBuilder Marshalling#3315
shrah merged 2 commits intodotnet:masterfrom
shrah:null

Conversation

@shrah
Copy link
Contributor

@shrah shrah commented Apr 12, 2017

We previously had only [OUT] UnicodeStringBuilder marshalling support. This change implements support for both Unicode and ANSI StringBuilder. It should also fix issue #2959

@shrah shrah changed the title Implement Unicode and Ansi StringBuilder Implement Unicode and Ansi StringBuilder Marshalling Apr 12, 2017
@shrah
Copy link
Contributor Author

shrah commented Apr 12, 2017

@yizhang82 PTAL

@shrah shrah requested a review from yizhang82 April 12, 2017 19:34
Copy link
Contributor

@yizhang82 yizhang82 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please fix the [out] case by splitting marshaling and allocation. Also please make sure the length calculation is done correctly in the border cases. This is a very tricky area and we should do it correctly the first time.

private static unsafe byte* CharArrayToAnsi(char* pStr, int stringLength)
{
// CORERT-TODO: Use same encoding as the rest of the interop
var encoding = Encoding.UTF8;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sigh... We should fix this...

// CORERT-TODO: Use same encoding as the rest of the interop
var encoding = Encoding.UTF8;
int bufferLength = encoding.GetByteCount(pStr, stringLength);
byte* buffer = (byte*)PInvokeMarshal.CoTaskMemAlloc((UIntPtr)(void*)(bufferLength + 1)).ToPointer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use UIntPtr(uint)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, note that you need to have separate the marshaling and the allocation. There are cases you only marshal, but without allocation. Example: Native -> Managed with [out]. Also, in that case, you might also need to pass the native array length to avoid overwriting the buffer. Finally, the allocation needs to be of the right size, which isn't necessarily the ansi char array size.

return null;
}

char* buffer = (char*)PInvokeMarshal.CoTaskMemAlloc((UIntPtr)(sizeof(char) * (sb.Capacity + 1))).ToPointer();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See the array case. You need to support [out] stringBuilder case correctly.

[DllImport("*", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]
private static extern int VerifyStringBuilder(StringBuilder sb);
[DllImport("*", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode, EntryPoint = "VerifyUnicodeStringBuilder")]
private static extern int VerifyUnicodeStringBuilder(StringBuilder sb);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add [out] stringbuilder case.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, where are the ansi array case? Please add [out] array case as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't support Ansi array case yet. I will send out another PR with that and add test cases for it.

@shrah
Copy link
Contributor Author

shrah commented Apr 25, 2017

I have send out a change for review in .NET Native to move the ANSI string marshalling helpers from S.P.Interop to S.P.CoreLIb. One that change is checked in and ported here, I will update this PR to hookup those helpers.

shrah added 2 commits April 25, 2017 16:27
It does the following:

* Enable support for correct ANSI marshalling semantics
   (dotnet#2476) by calling into PInvokeMarshal ANSI string marshalling helpers.
* Split Alloc and Transform for StringBuilder marshalling
* Added test case for [Out] StringBuilder marshalling
* Added null check in array marshaller.
@shrah
Copy link
Contributor Author

shrah commented Apr 26, 2017

@yizhang82 PTAL

@yizhang82
Copy link
Contributor

LGTM. Thanks!

@shrah shrah merged commit 5b6a7d1 into dotnet:master Apr 26, 2017
@shrah shrah deleted the null branch April 26, 2017 07:41
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants