This is an automated email from the ASF dual-hosted git repository. jbarrett pushed a commit to branch develop in repository https://gitbox.apache.org/repos/asf/geode-native.git
The following commit(s) were added to refs/heads/develop by this push: new b8fdb0f GEODE-9412: Fixes translation of String between .NET and C++ (#829) b8fdb0f is described below commit b8fdb0f7044cb78ba11898c2d0a3dbbc04f60cf0 Author: Jacob Barrett <jabarr...@vmware.com> AuthorDate: Thu Jul 8 11:56:07 2021 -0700 GEODE-9412: Fixes translation of String between .NET and C++ (#829) Adds new String.hpp similar to C++ client's string.hpp. Converts String to std::string via UTF-16 to UTF-8 transform. Converts std::string to String via UTF-8 to UTF-16 transform. Adds basic unit tests for String.hpp methods. Adds basic unit tests for Serializable. Splits the .NET library into objects and assembly so that unit tests can link directly against the objects to avoid symbol export issues crossing C++/CLI layers. Fixes ACE PDB location so it can be correctly included in dependent projects. --- clicache/src/CMakeLists.txt | 54 ++++++++++++++++++++++++------------- clicache/src/Serializable.cpp | 7 ++--- clicache/src/String.hpp | 54 +++++++++++++++++++++++++++++++++++++ clicache/test/CMakeLists.txt | 23 +++++++--------- clicache/test/SerializableTests.cpp | 49 +++++++++++++++++++++++++++++++++ clicache/test/StringTests.cpp | 45 +++++++++++++++++++++++++++++++ dependencies/ACE/CMakeLists.txt | 1 + 7 files changed, 198 insertions(+), 35 deletions(-) diff --git a/clicache/src/CMakeLists.txt b/clicache/src/CMakeLists.txt index ab5f454..16503f5 100644 --- a/clicache/src/CMakeLists.txt +++ b/clicache/src/CMakeLists.txt @@ -13,7 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.12) project(Apache.Geode CXX) if(NOT "${STRONG_NAME_PUBLIC_KEY}" STREQUAL "") @@ -23,8 +23,7 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/impl/AssemblyInfo.cpp.in ${CMAKE_CURR list(APPEND CONFIGURE_IN_FILES ${CMAKE_CURRENT_SOURCE_DIR}/impl/AssemblyInfo.cpp.in) list(APPEND CONFIGURE_OUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/impl/AssemblyInfo.cpp) -add_library(Apache.Geode SHARED - Apache.Geode.rc +add_library(Apache.Geode-object OBJECT AttributesMutator.cpp AttributesMutator.hpp begin_native.hpp @@ -194,6 +193,7 @@ add_library(Apache.Geode SHARED Struct.hpp StructSet.cpp StructSet.hpp + String.hpp SystemProperties.cpp SystemProperties.hpp TimeUtils.hpp @@ -210,7 +210,6 @@ add_library(Apache.Geode SHARED Utils.hpp impl/AppDomainContext.cpp impl/AppDomainContext.hpp - impl/AssemblyInfo.cpp.in impl/AuthenticatedView.cpp impl/AuthenticatedView.hpp impl/CacheListener.hpp @@ -298,23 +297,20 @@ add_library(Apache.Geode SHARED impl/TransactionListener.hpp impl/TransactionWriter.hpp impl/WeakhashMap.hpp - - ${CONFIGURE_OUT_FILES} ) -set_target_properties(Apache.Geode PROPERTIES - COMMON_LANGUAGE_RUNTIME "" - OUTPUT_NAME ${PRODUCT_DLL_NAME} +set_target_properties(Apache.Geode-object PROPERTIES + COMMON_LANGUAGE_RUNTIME "" VS_GLOBAL_CLRSupport "true" VS_GLOBAL_KEYWORD "ManagedCProj" VS_GLOBAL_PROJECT_TYPES "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}" - VS_GLOBAL_ROOTNAMESPACE ${PROJECT_NAME} + VS_GLOBAL_ROOTNAMESPACE Apache.Geode VS_DOTNET_REFERENCES "System;System.Xml;System.Core" FOLDER cli ) -target_compile_options(Apache.Geode - PRIVATE +target_compile_options(Apache.Geode-object + PUBLIC /bigobj # C1128 - large number of templates causes too many section. /Zm32 # C3859 - internal heap limit reached #/doc # Documents to xml @@ -324,21 +320,43 @@ target_compile_options(Apache.Geode /wd4947 /wd4251 /wd4635 ) -target_include_directories(Apache.Geode +target_include_directories(Apache.Geode-object PRIVATE $<TARGET_PROPERTY:apache-geode,SOURCE_DIR>/../src ) -target_link_libraries(Apache.Geode +target_link_libraries(Apache.Geode-object PUBLIC - psapi - PRIVATE c++cli c++11 apache-geode-static _WarningsAsError ) +add_library(Apache.Geode SHARED + Apache.Geode.rc + ${CONFIGURE_IN_FILES} + ${CONFIGURE_OUT_FILES} +) + +set_target_properties(Apache.Geode PROPERTIES + COMMON_LANGUAGE_RUNTIME "" + OUTPUT_NAME ${PRODUCT_DLL_NAME} + VS_GLOBAL_CLRSupport "true" + VS_GLOBAL_KEYWORD "ManagedCProj" + VS_GLOBAL_PROJECT_TYPES "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}" + VS_GLOBAL_ROOTNAMESPACE Apache.Geode + VS_DOTNET_REFERENCES "System;System.Xml;System.Core" + FOLDER cli +) + +target_link_libraries(Apache.Geode + PUBLIC + psapi + PRIVATE + Apache.Geode-object +) + target_link_options(Apache.Geode PRIVATE /DELAYLOAD:libssl-1_1-x64.dll @@ -351,7 +369,7 @@ set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${SHARED_LINKER_FLAG include(PrecompiledHeader) -add_precompiled_header(Apache.Geode geode_includes.hpp FORCEINCLUDE) +add_precompiled_header(Apache.Geode-object geode_includes.hpp FORCEINCLUDE) install(TARGETS Apache.Geode RUNTIME DESTINATION bin @@ -359,7 +377,7 @@ install(TARGETS Apache.Geode ) install ( - FILES $<TARGET_PDB_FILE:${PROJECT_NAME}> + FILES $<TARGET_PDB_FILE:Apache.Geode> DESTINATION bin CONFIGURATIONS Debug RelWithDebInfo ) diff --git a/clicache/src/Serializable.cpp b/clicache/src/Serializable.cpp index 34a222f..cc49f04 100644 --- a/clicache/src/Serializable.cpp +++ b/clicache/src/Serializable.cpp @@ -47,6 +47,7 @@ #include "impl/DotNetTypes.hpp" #include "CacheRegionHelper.hpp" #include "Cache.hpp" +#include "String.hpp" #pragma warning(disable:4091) @@ -387,17 +388,17 @@ namespace Apache { if (auto cacheableString = std::dynamic_pointer_cast<native::CacheableString>(nativeptr)) { - return marshal_as<String^>(cacheableString->value()); + return to_String(cacheableString->value()); } - return marshal_as<String^>(nativeptr->toString()); + return to_String(nativeptr->toString()); } std::shared_ptr<native::CacheableString> Serializable::GetCacheableString(String^ value) { std::shared_ptr<native::CacheableString> cStr; if (value) { - cStr = native::CacheableString::create(marshal_as<std::string>(value)); + cStr = native::CacheableString::create(to_utf8(value)); } else { cStr = std::dynamic_pointer_cast<native::CacheableString>(native::CacheableString::createDeserializable()); diff --git a/clicache/src/String.hpp b/clicache/src/String.hpp new file mode 100644 index 0000000..a18024a --- /dev/null +++ b/clicache/src/String.hpp @@ -0,0 +1,54 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#pragma once + +#include <string> +#include <codecvt> + +#include <msclr/marshal.h> +#include <msclr/marshal_cppstd.h> + +using namespace System; + +namespace Apache +{ + namespace Geode + { + namespace Client + { + + inline std::string to_utf8(const std::wstring& utf16) { + return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}.to_bytes(utf16); + } + + inline std::string to_utf8(String^ utf16) { + return to_utf8(msclr::interop::marshal_as<std::wstring>(utf16)); + } + + inline std::wstring to_wstring(const std::string& utf8) { + return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>{}.from_bytes(utf8); + } + + inline String^ to_String(const std::string& utf8) { + return msclr::interop::marshal_as<String^>(to_wstring(utf8)); + } + + } // namespace Client + } // namespace Geode +} // namespace Apache + diff --git a/clicache/test/CMakeLists.txt b/clicache/test/CMakeLists.txt index a47f10d..898a117 100644 --- a/clicache/test/CMakeLists.txt +++ b/clicache/test/CMakeLists.txt @@ -13,28 +13,28 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.12) project(Apache.Geode.Test CXX) set(vstest_dir ${CMAKE_BINARY_DIR}/packages/Microsoft.TestPlatform.16.8.3/tools/net451/Common7/IDE/Extensions/TestPlatform) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/packages.config ${CMAKE_CURRENT_BINARY_DIR}/packages.config COPYONLY) +list(APPEND CONFIGURE_IN_FILES ${CMAKE_CURRENT_SOURCE_DIR}/packages.config) +list(APPEND CONFIGURE_OUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/packages.config) -if(NOT "${STRONG_NAME_PUBLIC_KEY}" STREQUAL "") - set(STRONG_NAME_PUBLIC_KEY_ATTRIBUTE ", PublicKey=${STRONG_NAME_PUBLIC_KEY}") -endif() configure_file(${CMAKE_CURRENT_SOURCE_DIR}/AssemblyInfo.cpp.in ${CMAKE_CURRENT_BINARY_DIR}/AssemblyInfo.cpp) list(APPEND CONFIGURE_IN_FILES ${CMAKE_CURRENT_SOURCE_DIR}/AssemblyInfo.cpp.in) list(APPEND CONFIGURE_OUT_FILES ${CMAKE_CURRENT_BINARY_DIR}/AssemblyInfo.cpp) add_library(Apache.Geode.Test MODULE - AssemblyInfo.cpp.in native_conditional_unqiue_ptrTests.cpp native_shared_ptrTests.cpp native_unique_ptrTests.cpp TimeUtilsTests.cpp + SerializableTests.cpp + StringTests.cpp + ${CONFIGURE_IN_FILES} ${CONFIGURE_OUT_FILES} - packages.config ) set_target_properties(Apache.Geode.Test PROPERTIES @@ -52,27 +52,22 @@ set_target_properties(Apache.Geode.Test PROPERTIES target_include_directories(Apache.Geode.Test PRIVATE - $<TARGET_PROPERTY:apache-geode,SOURCE_DIR> + $<TARGET_PROPERTY:apache-geode,SOURCE_DIR>/../src $<TARGET_PROPERTY:apache-geode,INCLUDE_DIRECTORIES> - $<TARGET_PROPERTY:Apache.Geode,SOURCE_DIR> + $<TARGET_PROPERTY:Apache.Geode-object,SOURCE_DIR> ) target_link_libraries(Apache.Geode.Test PUBLIC - # Apache.Geode #- Causes include of .lib + Apache.Geode-object PRIVATE c++cli c++11 _WarningsAsError ) -# Makes project only reference, no .lib. -add_dependencies(Apache.Geode.Test Apache.Geode) add_dependencies(Apache.Geode.Test nuget-restore) -string(REPLACE "/RTC1" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") -set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${SHARED_LINKER_FLAGS_STRONG_KEY}") - # For Visual Studio organization source_group("Configure In Files" FILES ${CONFIGURE_IN_FILES}) source_group("Configure Out Files" FILES ${CONFIGURE_OUT_FILES}) diff --git a/clicache/test/SerializableTests.cpp b/clicache/test/SerializableTests.cpp new file mode 100644 index 0000000..c4eddd1 --- /dev/null +++ b/clicache/test/SerializableTests.cpp @@ -0,0 +1,49 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "Serializable.hpp" +#include <geode/CacheableString.hpp> + +using namespace System; +using namespace System::Text; +using namespace System::Collections::Generic; +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; + +using Apache::Geode::Client::Serializable; + +[TestClass] +public ref class SerializableTests +{ +public: + + [TestMethod] + void GetCacheableStringHandlesNonAsciiCharacters() + { + auto cacheableString = Serializable::GetCacheableString(gcnew String(L"foo\u2019s\U00010003")); + Assert::IsFalse(cacheableString.get() == nullptr); + Assert::IsTrue(std::string("foo\xE2\x80\x99s\xf0\x90\x80\x83") == cacheableString->value()); + } + + [TestMethod] + void GetStringHandlesNonAsciiCharacters() + { + auto cacheableString = apache::geode::client::CacheableString::create("foo\xE2\x80\x99s\xf0\x90\x80\x83"); + auto str = Serializable::getString(cacheableString); + Assert::AreEqual(gcnew String(L"foo\u2019s\U00010003"), str); + } + +}; diff --git a/clicache/test/StringTests.cpp b/clicache/test/StringTests.cpp new file mode 100644 index 0000000..bef1349 --- /dev/null +++ b/clicache/test/StringTests.cpp @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "String.hpp" + +using namespace System; +using namespace Microsoft::VisualStudio::TestTools::UnitTesting; +using namespace Apache::Geode::Client; + +[TestClass] +public ref class StringTests +{ +public: + + [TestMethod] + void to_uft8FromStringHandlesNonAscii() + { + String^ str = L"foo\u2019s\U00010003"; + auto utf8 = to_utf8(str); + Assert::IsTrue(std::string("foo\xE2\x80\x99s\xf0\x90\x80\x83") == utf8); + } + + + [TestMethod] + void to_StringFromUtf8HandlesNonAscii() + { + std::string utf8("foo\xE2\x80\x99s\xf0\x90\x80\x83"); + auto str = to_String(utf8); + Assert::AreEqual(gcnew String(L"foo\u2019s\U00010003"), str); + } +}; diff --git a/dependencies/ACE/CMakeLists.txt b/dependencies/ACE/CMakeLists.txt index d8c12e1..dd546e3 100644 --- a/dependencies/ACE/CMakeLists.txt +++ b/dependencies/ACE/CMakeLists.txt @@ -89,6 +89,7 @@ if (${WIN32}) ) set ( _INSTALL_COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/lib <INSTALL_DIR>/lib COMMAND ${CMAKE_COMMAND} -E copy_directory <SOURCE_DIR>/ace <INSTALL_DIR>/include/ace + COMMAND ${CMAKE_COMMAND} -E copy <SOURCE_DIR>/ace/Static_$<$<CONFIG:Debug>:Debug>$<$<NOT:$<CONFIG:Debug>>:Release>/ace_${MPC_TYPE}_static/AMD64/ACE_${MPC_TYPE}_static.pdb <INSTALL_DIR>/lib ) set(CMAKE_STATIC_LIBRARY_SUFFIX s$<${MSVC}:$<$<CONFIG:Debug>:d>>.lib)