diff options
Diffstat (limited to 'tests/src')
-rw-r--r-- | tests/src/Interop/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/src/Interop/StringMarshalling/UTF8/CMakeLists.txt | 9 | ||||
-rw-r--r-- | tests/src/Interop/StringMarshalling/UTF8/UTF8Test.cs | 221 | ||||
-rw-r--r-- | tests/src/Interop/StringMarshalling/UTF8/UTF8Test.csproj | 50 | ||||
-rw-r--r-- | tests/src/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp | 314 | ||||
-rw-r--r-- | tests/src/Interop/StringMarshalling/UTF8/project.json | 15 |
6 files changed, 610 insertions, 0 deletions
diff --git a/tests/src/Interop/CMakeLists.txt b/tests/src/Interop/CMakeLists.txt index af51c5e665..370b699391 100644 --- a/tests/src/Interop/CMakeLists.txt +++ b/tests/src/Interop/CMakeLists.txt @@ -14,5 +14,6 @@ add_subdirectory(RefInt) add_subdirectory(RefCharArray) add_subdirectory(StringMarshalling/LPSTR) add_subdirectory(StringMarshalling/LPTSTR) +add_subdirectory(StringMarshalling/UTF8) add_subdirectory(MarshalAPI/FunctionPointer) add_subdirectory(MarshalAPI/IUnknown) diff --git a/tests/src/Interop/StringMarshalling/UTF8/CMakeLists.txt b/tests/src/Interop/StringMarshalling/UTF8/CMakeLists.txt new file mode 100644 index 0000000000..1e8edbf563 --- /dev/null +++ b/tests/src/Interop/StringMarshalling/UTF8/CMakeLists.txt @@ -0,0 +1,9 @@ +cmake_minimum_required (VERSION 2.6) +project (UTF8TestNative) +set(SOURCES UTF8TestNative.cpp ) + +# add the executable +add_library (UTF8TestNative SHARED ${SOURCES}) + +# add the install targets +install (TARGETS UTF8TestNative DESTINATION bin)
\ No newline at end of file diff --git a/tests/src/Interop/StringMarshalling/UTF8/UTF8Test.cs b/tests/src/Interop/StringMarshalling/UTF8/UTF8Test.cs new file mode 100644 index 0000000000..7bfe19fdac --- /dev/null +++ b/tests/src/Interop/StringMarshalling/UTF8/UTF8Test.cs @@ -0,0 +1,221 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Runtime.InteropServices; +using System.Text; +using System.Collections.Generic; + + +// UTF8 +class UTF8StringTests +{ + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPUTF8Str)] + public static extern string StringParameterInOut([In, Out][MarshalAs(UnmanagedType.LPUTF8Str)]string s, int index); + public static void TestInOutStringParameter(string orgString, int index) + { + string passedString = orgString; + string expectedNativeString = passedString; + + string nativeString = StringParameterInOut(passedString, index); + if (!(nativeString == expectedNativeString)) + { + throw new Exception("StringParameterInOut: nativeString != expecedNativeString "); + } + } + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPUTF8Str)] + public static extern string StringParameterOut([Out][MarshalAs(UnmanagedType.LPUTF8Str)]string s, int index); + public static void TestOutStringParameter(string orgString, int index) + { + string passedString = orgString; + string expecedNativeString = passedString; + string nativeString = StringParameterInOut(passedString, index); + if (!(nativeString == expecedNativeString)) + { + throw new Exception("StringParameterInOut: nativeString != expecedNativeString "); + } + } + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void StringParameterRefOut([MarshalAs(UnmanagedType.LPUTF8Str)]out string s, int index); + public static void TestStringPassByOut(string orgString, int index) + { + // out string + string expectedNative = string.Empty; + StringParameterRefOut(out expectedNative, index); + if (orgString != expectedNative) + { + throw new Exception("TestStringPassByOut : expectedNative != outString"); + } + } + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void StringParameterRef([MarshalAs(UnmanagedType.LPUTF8Str)]ref string s, int index); + public static void TestStringPassByRef(string orgString, int index) + { + string orgCopy = new string(orgString.ToCharArray()); + StringParameterRef(ref orgString, index); + if (orgString != orgCopy) + { + throw new Exception("TestStringPassByOut : string mismatch"); + } + } + + public static void EmptyStringTest() + { + StringParameterInOut(string.Empty, 0); + StringParameterOut(string.Empty, 0); + } +} + +// UTF8 stringbuilder +class UTF8StringBuilderTests +{ + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void StringBuilderParameterInOut([In, Out][MarshalAs(UnmanagedType.LPUTF8Str)]StringBuilder s, int index); + public static void TestInOutStringBuilderParameter(string expectedString, int index) + { + StringBuilder nativeStrBuilder = new StringBuilder(expectedString); + StringBuilderParameterInOut(nativeStrBuilder, index); + + if (!nativeStrBuilder.ToString().Equals(expectedString)) + { + throw new Exception("TestInOutStringBuilderParameter: nativeString != expecedNativeString "); + } + } + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void StringBuilderParameterOut([Out][MarshalAs(UnmanagedType.LPUTF8Str)]StringBuilder s, int index); + public static void TestOutStringBuilderParameter(string expectedString, int index) + { + // string builder capacity + StringBuilder nativeStringBuilder = new StringBuilder(expectedString.Length); + StringBuilderParameterOut(nativeStringBuilder, index); + + if (!nativeStringBuilder.ToString().Equals(expectedString)) + { + throw new Exception("TestOutStringBuilderParameter: string != expecedString "); + } + } + + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + [return: MarshalAs(UnmanagedType.LPUTF8Str,SizeConst = 512)] + public static extern StringBuilder StringBuilderParameterReturn(int index); + public static void TestReturnStringBuilder(string expectedReturn, int index) + { + StringBuilder nativeString = StringBuilderParameterReturn(index); + if (!expectedReturn.Equals(nativeString.ToString())) + { + throw new Exception(string.Format( "TestReturnStringBuilder: nativeString {0} != expecedNativeString {1}",nativeString.ToString(),expectedReturn) ); + } + } +} + +// UTF8 string as struct field +class UTF8StructMarshalling +{ + public struct Utf8Struct + { + [MarshalAs(UnmanagedType.LPUTF8Str)] + public string FirstName; + public int index; + } + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void TestStructWithUtf8Field(Utf8Struct utfStruct); + public static void TestUTF8StructMarshalling(string[] utf8Strings) + { + Utf8Struct utf8Struct = new Utf8Struct(); + for (int i = 0; i < utf8Strings.Length; i++) + { + utf8Struct.FirstName = utf8Strings[i]; + utf8Struct.index = i; + TestStructWithUtf8Field(utf8Struct); + } + } +} + +// UTF8 string as delegate parameter +class UTF8DelegateMarshalling +{ + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void DelegateUTF8Parameter([MarshalAs(UnmanagedType.LPUTF8Str)]string utf8String, int index); + + + [DllImport("UTF8TestNative", CallingConvention = CallingConvention.Cdecl)] + public static extern void Utf8DelegateAsParameter(DelegateUTF8Parameter param); + + + public static void TestUTF8DelegateMarshalling() + { + Utf8DelegateAsParameter(new DelegateUTF8Parameter(Utf8StringCallback)); + } + + public static void Utf8StringCallback(string nativeString, int index) + { + if (string.CompareOrdinal(nativeString, Test.utf8Strings[index]) != 0) + { + throw new Exception("Utf8StringCallback string do not match"); + } + } +} + +class Test +{ + //test strings + public static string[] utf8Strings = { + "Managed", + "Sîne klâwen durh die wolken sint geslagen" , + "काचं शक्नोम्यत्तुम् । नोपहिनस्ति माम्", + "我能吞下玻璃而不伤身体", + "ღმერთსი შემვედრე,შემვედრე, ნუთუ კვლა დამხსნას შემვედრე,სოფლისა შემვედრე, შემვედრე,შემვედრე,შემვედრე,შრომასა, ცეცხლს, წყალსა და მიწასა, ჰაერთა თანა მრომასა; მომცნეს ფრთენი და აღვფრინდე, მივჰხვდე მას ჩემსა ნდომასა, დღისით და ღამით ვჰხედვიდე მზისა ელვათა კრთომაასაშემვედრე,შემვედრე,", + "Τη γλώσσα μου έδωσαν ελληνική", + null, + }; + + public static int Main(string[] args) + { + // Test string as [In,Out] parameter + for (int i = 0; i < utf8Strings.Length; i++) + UTF8StringTests.TestInOutStringParameter(utf8Strings[i], i); + + // Test string as [Out] parameter + for (int i = 0; i < utf8Strings.Length; i++) + UTF8StringTests.TestOutStringParameter(utf8Strings[i], i); + + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringTests.TestStringPassByOut(utf8Strings[i], i); + + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringTests.TestStringPassByRef(utf8Strings[i], i); + + + // Test StringBuilder as [In,Out] parameter + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringBuilderTests.TestInOutStringBuilderParameter(utf8Strings[i], i); + + // Test StringBuilder as [Out] parameter + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringBuilderTests.TestOutStringBuilderParameter(utf8Strings[i], i); + + // utf8 string as struct fields + UTF8StructMarshalling.TestUTF8StructMarshalling(utf8Strings); + + // delegate + UTF8DelegateMarshalling.TestUTF8DelegateMarshalling(); + + // Test StringBuilder as [Out] parameter + for (int i = 0; i < utf8Strings.Length - 1; i++) + UTF8StringBuilderTests.TestReturnStringBuilder(utf8Strings[i], i); + + // String.Empty tests + UTF8StringTests.EmptyStringTest(); + + return 100; + } +}
\ No newline at end of file diff --git a/tests/src/Interop/StringMarshalling/UTF8/UTF8Test.csproj b/tests/src/Interop/StringMarshalling/UTF8/UTF8Test.csproj new file mode 100644 index 0000000000..8884419a6b --- /dev/null +++ b/tests/src/Interop/StringMarshalling/UTF8/UTF8Test.csproj @@ -0,0 +1,50 @@ +<?xml version="1.0" encoding="utf-8"?> +<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.props))\dir.props" /> + <PropertyGroup> + <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> + <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> + <AssemblyName>UTF8Test</AssemblyName> + <SchemaVersion>2.0</SchemaVersion> + <ProjectGuid>{F1E66554-8C8E-4141-85CF-D0CD6A0CD0B0}</ProjectGuid> + <OutputType>exe</OutputType> + <AppDesignerFolder>Properties</AppDesignerFolder> + <FileAlignment>512</FileAlignment> + <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> + <ReferencePath>$(ProgramFiles)\Common Files\microsoft shared\VSTT\11.0\UITestExtensionPackages</ReferencePath> + <SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\..\</SolutionDir> + <AllowUnsafeBlocks>true</AllowUnsafeBlocks> + <NuGetPackageImportStamp>7a9bfb7d</NuGetPackageImportStamp> + <DefineConstants>$(DefineConstants);STATIC</DefineConstants> + <ReferenceLocalMscorlib>true</ReferenceLocalMscorlib> + </PropertyGroup> + <!-- Default configurations to help VS understand the configurations --> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'"> + </PropertyGroup> + <PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'"> + </PropertyGroup> + <ItemGroup> + <CodeAnalysisDependentAssemblyPaths Condition=" '$(VS100COMNTOOLS)' != '' " Include="$(VS100COMNTOOLS)..\IDE\PrivateAssemblies"> + <Visible>False</Visible> + </CodeAnalysisDependentAssemblyPaths> + </ItemGroup> + <ItemGroup> + <Compile Include="*.cs" /> + <Compile Include="..\..\common\Assertion.cs" /> + </ItemGroup> + <ItemGroup> + <None Include="project.json" /> + </ItemGroup> + <ItemGroup> + <Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" /> + </ItemGroup> + <ItemGroup> + <ProjectReference Include="..\..\..\Common\CoreCLRTestLibrary\CoreCLRTestLibrary.csproj"> + <Project>{c8c0dc74-fac4-45b1-81fe-70c4808366e0}</Project> + <Name>CoreCLRTestLibrary</Name> + </ProjectReference> + <ProjectReference Include="CMakeLists.txt"> + </ProjectReference> + </ItemGroup> + <Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory), dir.targets))\dir.targets" /> +</Project>
\ No newline at end of file diff --git a/tests/src/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp b/tests/src/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp new file mode 100644 index 0000000000..77e4b9c8cb --- /dev/null +++ b/tests/src/Interop/StringMarshalling/UTF8/UTF8TestNative.cpp @@ -0,0 +1,314 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#include <xplatform.h> + +// helper functions +#ifdef _WIN32 +char* UTF16ToUTF8(wchar_t * pszTextUTF16) +{ + if ((pszTextUTF16 == NULL) || (*pszTextUTF16 == L'\0')) { + return 0; + } + + size_t cchUTF16; + cchUTF16 = wcslen(pszTextUTF16) + 1; + int cbUTF8 = WideCharToMultiByte(CP_UTF8, 0, + pszTextUTF16, + (int)cchUTF16, + NULL, + 0/* request buffer size*/, + NULL, + NULL); + + char *pszUTF8 = (char*)CoTaskMemAlloc(sizeof(char) * (cbUTF8 + 1)); + int nc = WideCharToMultiByte(CP_UTF8, // convert to UTF-8 + 0, //default flags + pszTextUTF16, //source wide string + (int)cchUTF16, // length of wide string + pszUTF8, // destination buffer + cbUTF8, // destination buffer size + NULL, + NULL); + + if (!nc) + { + throw; + } + + pszUTF8[nc] = '\0'; + return pszUTF8; +} + +wchar_t* UTF8ToUTF16(const char *utf8) +{ + // Special case of empty input string + //wszTextUTF16 + wchar_t *wszTextUTF16 = 0; + if (!utf8 || !(*utf8)) + return wszTextUTF16; + size_t szUtf8 = strlen(utf8); + + //Get length (in wchar_t's) of resulting UTF-16 string + int cbUTF16 = ::MultiByteToWideChar( + CP_UTF8, // convert from UTF-8 + 0, // default flags + utf8, // source UTF-8 string + (int)szUtf8, // length (in chars) of source UTF-8 string + NULL, // unused - no conversion done in this step + 0 // request size of destination buffer, in wchar_t's + ); + + wszTextUTF16 = (wchar_t*)(CoTaskMemAlloc((cbUTF16 + 1 ) * sizeof(wchar_t) )); + // Do the actual conversion from UTF-8 to UTF-16 + int nc = ::MultiByteToWideChar( + CP_UTF8, // convert from UTF-8 + 0, // default flags + utf8, // source UTF-8 string + (int)szUtf8, // length (in chars) of source UTF-8 string + wszTextUTF16, // destination buffer + cbUTF16); // size of destination buffer, in wchar_t's + + if (!nc) + { + throw; + } + //MultiByteToWideChar do not null terminate the string when cbMultiByte is not -1 + wszTextUTF16[nc] = '\0'; + return wszTextUTF16; +} +#endif + + +LPSTR build_return_string(const char* pReturn) +{ + char *ret = 0; + if (pReturn == 0 || *pReturn == 0) + return ret; + + size_t strLength = strlen(pReturn); + ret = (LPSTR)(CoTaskMemAlloc(sizeof(char)* (strLength + 1))); + memset(ret, '\0', strLength + 1); + strncpy_s(ret, strLength + 1, pReturn, strLength); + return ret; +} + +// this is the same set as in managed side , but here +// string need to be escaped , still CL applied some local and +// end up with different byte sequence. + +const int NSTRINGS = 6; +#ifdef _WIN32 +wchar_t *utf8Strings[] = { L"Managed", +L"S\x00EEne kl\x00E2wen durh die wolken sint geslagen" , +L"\x0915\x093E\x091A\x0902 \x0936\x0915\x094D\x0928\x094B\x092E\x094D\x092F\x0924\x094D\x0924\x0941\x092E\x094D \x0964 \x0928\x094B\x092A\x0939\x093F\x0928\x0938\x094D\x0924\x093F \x092E\x093E\x092E\x094D", +L"\x6211\x80FD\x541E\x4E0B\x73BB\x7483\x800C\x4E0D\x4F24\x8EAB\x4F53", +L"\x10E6\x10DB\x10D4\x10E0\x10D7\x10E1\x10D8 \x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4,\x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4, \x10DC\x10E3\x10D7\x10E3 \x10D9\x10D5\x10DA\x10D0 \x10D3\x10D0\x10DB\x10EE\x10E1\x10DC\x10D0\x10E1 \x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4,\x10E1\x10DD\x10E4\x10DA\x10D8\x10E1\x10D0 \x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4, \x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4,\x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4,\x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4,\x10E8\x10E0\x10DD\x10DB\x10D0\x10E1\x10D0, \x10EA\x10D4\x10EA\x10EE\x10DA\x10E1, \x10EC\x10E7\x10D0\x10DA\x10E1\x10D0 \x10D3\x10D0 \x10DB\x10D8\x10EC\x10D0\x10E1\x10D0, \x10F0\x10D0\x10D4\x10E0\x10D7\x10D0 \x10D7\x10D0\x10DC\x10D0 \x10DB\x10E0\x10DD\x10DB\x10D0\x10E1\x10D0; \x10DB\x10DD\x10DB\x10EA\x10DC\x10D4\x10E1 \x10E4\x10E0\x10D7\x10D4\x10DC\x10D8 \x10D3\x10D0 \x10D0\x10E6\x10D5\x10E4\x10E0\x10D8\x10DC\x10D3\x10D4, \x10DB\x10D8\x10D5\x10F0\x10EE\x10D5\x10D3\x10D4 \x10DB\x10D0\x10E1 \x10E9\x10D4\x10DB\x10E1\x10D0 \x10DC\x10D3\x10DD\x10DB\x10D0\x10E1\x10D0, \x10D3\x10E6\x10D8\x10E1\x10D8\x10D7 \x10D3\x10D0 \x10E6\x10D0\x10DB\x10D8\x10D7 \x10D5\x10F0\x10EE\x10D4\x10D3\x10D5\x10D8\x10D3\x10D4 \x10DB\x10D6\x10D8\x10E1\x10D0 \x10D4\x10DA\x10D5\x10D0\x10D7\x10D0 \x10D9\x10E0\x10D7\x10DD\x10DB\x10D0\x10D0\x10E1\x10D0\x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4,\x10E8\x10D4\x10DB\x10D5\x10D4\x10D3\x10E0\x10D4,", +L"\x03A4\x03B7 \x03B3\x03BB\x03CE\x03C3\x03C3\x03B1 \x03BC\x03BF\x03C5 \x03AD\x03B4\x03C9\x03C3\x03B1\x03BD \x03B5\x03BB\x03BB\x03B7\x03BD\x03B9\x03BA\x03AE", +L"\0" +}; + +#else +//test strings +const char *utf8Strings[] = { "Managed", +"Sîne klâwen durh die wolken sint geslagen", +"काचं शक्नोम्यत्तुम् । नोपहिनस्ति माम्", +"我能吞下玻璃而不伤身体", +"ღმერთსი შემვედრე,შემვედრე, ნუთუ კვლა დამხსნას შემვედრე,სოფლისა შემვედრე, შემვედრე,შემვედრე,შემვედრე,შრომასა, ცეცხლს, წყალსა და მიწასა, ჰაერთა თანა მრომასა; მომცნეს ფრთენი და აღვფრინდე, მივჰხვდე მას ჩემსა ნდომასა, დღისით და ღამით ვჰხედვიდე მზისა ელვათა კრთომაასაშემვედრე,შემვედრე,", +"Τη γλώσσα μου έδωσαν ελληνική", +"\0" +}; +#endif + +// Modify the string builder in place, managed side validates. +extern "C" DLL_EXPORT void __cdecl StringBuilderParameterInOut(/*[In,Out] StringBuilder*/ char *s, int index) +{ + // if string.empty + if (s == 0 || *s == 0) + return; + +#ifdef _WIN32 + char *pszTextutf8 = UTF16ToUTF8(utf8Strings[index]); +#else + char *pszTextutf8 = (char*)utf8Strings[index]; +#endif + + // do byte by byte validation of in string + size_t szLen = strlen(s); + for (size_t i = 0; i < szLen; i++) + { + if (s[i] != pszTextutf8[i]) + { + printf("[in] managed string do not match native string\n"); + throw; + } + } + + // modify the string inplace + size_t outLen = strlen(pszTextutf8); + for (size_t i = 0; i < outLen; i++) { + s[i] = pszTextutf8[i]; + } + s[outLen] = '\0'; +#ifdef _WIN32 + CoTaskMemFree(pszTextutf8); +#endif +} + +//out string builder +extern "C" DLL_EXPORT void __cdecl StringBuilderParameterOut(/*[Out] StringBuilder*/ char *s, int index) +{ + +#ifdef _WIN32 + char *pszTextutf8 = UTF16ToUTF8(utf8Strings[index]); +#else + char *pszTextutf8 = (char*)utf8Strings[index]; +#endif + // modify the string inplace + size_t outLen = strlen(pszTextutf8); + for (size_t i = 0; i < outLen; i++) { + s[i] = pszTextutf8[i]; + } + s[outLen] = '\0'; +#ifdef _WIN32 + CoTaskMemFree(pszTextutf8); +#endif +} + +// return utf8 stringbuilder +extern "C" DLL_EXPORT char* __cdecl StringBuilderParameterReturn(int index) { + +#ifdef _WIN32 + char *pszTextutf8 = UTF16ToUTF8(utf8Strings[index]); +#else + char *pszTextutf8 = (char*)utf8Strings[index]; +#endif + size_t strLength = strlen(pszTextutf8); + LPSTR ret = (LPSTR)(CoTaskMemAlloc(sizeof(char)* (strLength + 1))); + memcpy(ret, pszTextutf8, strLength); + ret[strLength] = '\0'; + +#ifdef _WIN32 + CoTaskMemFree(pszTextutf8); +#endif + + return ret; +} + +extern "C" DLL_EXPORT LPSTR __cdecl StringParameterOut(/*[Out]*/ char *s, int index) +{ + // return a copy + return build_return_string(s); +} + +// string +extern "C" DLL_EXPORT LPSTR __cdecl StringParameterInOut(/*[In,Out]*/ char *s, int index) +{ + // return a copy + return build_return_string(s); +} + +// Utf8 field +typedef struct FieldWithUtf8 +{ + char *pFirst; + int index; +}FieldWithUtf8; + +//utf8 struct field +extern "C" DLL_EXPORT void _cdecl TestStructWithUtf8Field(struct FieldWithUtf8 fieldStruct) +{ + char *pszManagedutf8 = fieldStruct.pFirst; + int stringIndex = fieldStruct.index; + char *pszNative = 0; + size_t outLen = 0; + + if (pszManagedutf8 == 0 || *pszManagedutf8 == 0) + return; + +#ifdef _WIN32 + pszNative = UTF16ToUTF8(utf8Strings[stringIndex]); +#else + pszNative = (char*)utf8Strings[stringIndex]; +#endif + outLen = strlen(pszNative); + // do byte by byte comparision + for (size_t i = 0; i < outLen; i++) + { + if (pszNative[i] != pszManagedutf8[i]) + { + printf("Native and managed string do not match.\n"); + throw; + } + } +#ifdef _WIN32 + CoTaskMemFree(pszNative); +#endif +} + +// test c# out keyword +extern "C" DLL_EXPORT void __cdecl StringParameterRefOut(/*out*/ char **s, int index) +{ +#ifdef _WIN32 + char *pszTextutf8 = UTF16ToUTF8(utf8Strings[index]); +#else + char *pszTextutf8 = (char*)utf8Strings[index]; +#endif + size_t strLength = strlen(pszTextutf8); + *s = (LPSTR)(CoTaskMemAlloc(sizeof(char)* (strLength + 1))); + memcpy(*s, pszTextutf8, strLength); + (*s)[strLength] = '\0'; +#ifdef _WIN32 + CoTaskMemFree(pszTextutf8); +#endif +} + +//c# ref +extern "C" DLL_EXPORT void __cdecl StringParameterRef(/*ref*/ char **s, int index) +{ +#ifdef _WIN32 + char *pszTextutf8 = UTF16ToUTF8(utf8Strings[index]); +#else + char *pszTextutf8 = (char*)utf8Strings[index]; +#endif + size_t strLength = strlen(pszTextutf8); + // do byte by byte validation of in string + size_t szLen = strlen(*s); + for (size_t i = 0; i < szLen; i++) + { + if ((*s)[i] != pszTextutf8[i]) + { + printf("[in] managed string do not match native string\n"); + throw; + } + } + + if (*s) + { + CoTaskMemFree(*s); + } + // overwrite the orginal + *s = (LPSTR)(CoTaskMemAlloc(sizeof(char)* (strLength + 1))); + memcpy(*s, pszTextutf8, strLength); + (*s)[strLength] = '\0'; +#ifdef _WIN32 + CoTaskMemFree(pszTextutf8); +#endif +} + +// delegate test +typedef void (__cdecl * Callback)(char *text, int index); +extern "C" DLL_EXPORT void _cdecl Utf8DelegateAsParameter(Callback managedCallback) +{ + for (int i = 0; i < NSTRINGS; ++i) + { + char *pszNative = 0; +#ifdef _WIN32 + pszNative = UTF16ToUTF8(utf8Strings[i]); +#else + pszNative = (char*)utf8Strings[i]; +#endif + managedCallback(pszNative, i); + } +}
\ No newline at end of file diff --git a/tests/src/Interop/StringMarshalling/UTF8/project.json b/tests/src/Interop/StringMarshalling/UTF8/project.json new file mode 100644 index 0000000000..fc3f0262a9 --- /dev/null +++ b/tests/src/Interop/StringMarshalling/UTF8/project.json @@ -0,0 +1,15 @@ +{ + "dependencies": {}, + "frameworks": { + "dnxcore50": {} + }, + "runtimes": { + "win7-x86": {}, + "win7-x64": {}, + "ubuntu.14.04-x64": {}, + "osx.10.10-x64": {}, + "centos.7-x64": {}, + "rhel.7-x64": {}, + "debian.8.2-x64": {} + } +} |