From a72c43fd2fe7c2ce1713cecdb072b7f9ee269a71 Mon Sep 17 00:00:00 2001 From: Elias Holzer Date: Mon, 28 Apr 2014 15:18:58 +0200 Subject: [PATCH] Added marshaling code for std::ostream using a System.TextWriter to CLI backend. --- include/CppSharp.h | 79 +++++++++++++++++++++++++++++++ src/Generator/Types/Std/Stdlib.cs | 19 ++++++++ tests/STL/STL.Tests.cs | 17 +++++-- tests/STL/STL.h | 9 ++++ 4 files changed, 120 insertions(+), 4 deletions(-) diff --git a/include/CppSharp.h b/include/CppSharp.h index 9941a936..f84c1378 100644 --- a/include/CppSharp.h +++ b/include/CppSharp.h @@ -9,7 +9,9 @@ #pragma once #include +#include #include +#include public interface class ICppInstance { @@ -212,3 +214,80 @@ namespace clix { } } // namespace clix + +// std::ostream marshaling using a System::IO::TextWriter +namespace msclr { + namespace interop { + namespace details { + class text_writer_streambuf : public std::streambuf + { + public: + text_writer_streambuf(const gcroot & tw) + : std::streambuf() + { + m_tw = tw; + } + ~text_writer_streambuf() + { + m_tw->Flush(); + } + int_type overflow(int_type ch) + { + if (traits_type::not_eof(ch)) + { + auto c = traits_type::to_char_type(ch); + xsputn(&c, 1); + } + return traits_type::not_eof(ch); + } + std::streamsize xsputn(const char *_Ptr, std::streamsize _Count) + { + auto s = gcnew System::String(_Ptr, 0, _Count, System::Text::Encoding::UTF8); + m_tw->Write(s); + return _Count; + } + private: + gcroot m_tw; + }; + + class text_writer_ostream : public std::ostream { + public: + text_writer_ostream(const gcroot & s) : + std::ios(), + std::ostream(0), + m_sbuf(s) + { + init(&m_sbuf); + } + private: + text_writer_streambuf m_sbuf; + }; + } + + template<> + ref class context_node : public context_node_base + { + private: + std::ostream* toPtr; + public: + context_node(std::ostream*& toObject, System::IO::TextWriter^ fromObject) + { + // (Step 4) Initialize toPtr to the appropriate empty value. + toPtr = new details::text_writer_ostream(fromObject); + // (Step 5) Insert conversion logic here. + // (Step 6) Set toObject to the converted parameter. + toObject = toPtr; + } + ~context_node() + { + this->!context_node(); + } + protected: + !context_node() + { + // (Step 7) Clean up native resources. + delete toPtr; + } + }; + } +} // namespace msclr diff --git a/src/Generator/Types/Std/Stdlib.cs b/src/Generator/Types/Std/Stdlib.cs index 14a88abd..f06cfcd4 100644 --- a/src/Generator/Types/Std/Stdlib.cs +++ b/src/Generator/Types/Std/Stdlib.cs @@ -293,4 +293,23 @@ namespace CppSharp.Types.Std throw new System.NotImplementedException(); } } + + [TypeMap("std::ostream")] + public class OStream : TypeMap + { + public override string CLISignature(CLITypePrinterContext ctx) + { + return "System::IO::TextWriter^"; + } + + public override void CLIMarshalToNative(MarshalContext ctx) + { + var marshal = ctx.MarshalToNative as CLIMarshalManagedToNativePrinter; + marshal.ArgumentPrefix.Write("*"); + var marshalCtxName = string.Format("ctx_{0}", ctx.Parameter.Name); + ctx.SupportBefore.WriteLine("msclr::interop::marshal_context {0};", marshalCtxName); + ctx.Return.Write("{0}.marshal_as({1})", + marshalCtxName, ctx.Parameter.Name); + } + } } diff --git a/tests/STL/STL.Tests.cs b/tests/STL/STL.Tests.cs index c8f6a961..b3fd19ed 100644 --- a/tests/STL/STL.Tests.cs +++ b/tests/STL/STL.Tests.cs @@ -1,10 +1,10 @@ -using System; +using CppSharp.Utils; +using NUnit.Framework; +using STL; using System.Collections.Generic; +using System.IO; using System.Linq; -using CppSharp.Utils; -using NUnit.Framework; using System.Runtime.InteropServices; -using STL; public class STLTests : GeneratorTestFixture { @@ -47,5 +47,14 @@ public class STLTests : GeneratorTestFixture for (int i = 0; i < 3; i++) Assert.AreEqual(i, valueTypeWrapperList[i].Value); } + + [Test] + public void TestOStream() + { + const string testString = "hello wörld"; + var stringWriter = new StringWriter(); + OStreamTest.WriteToOStream(stringWriter, testString); + Assert.AreEqual(testString, stringWriter.ToString()); + } } \ No newline at end of file diff --git a/tests/STL/STL.h b/tests/STL/STL.h index 3a344fc2..e9c04dea 100644 --- a/tests/STL/STL.h +++ b/tests/STL/STL.h @@ -1,5 +1,6 @@ #include "../Tests.h" #include +#include struct DLL_API IntWrapper { @@ -28,3 +29,11 @@ struct DLL_API TestVectors // Should get mapped to List std::vector IntWrapperValueTypeVector; }; + +struct DLL_API OStreamTest +{ + static void WriteToOStream(std::ostream& stream, const char* s) + { + stream << s; + }; +}; \ No newline at end of file