Browse Source

Merge pull request #236 from azeno/stl-typemaps

STL type maps
pull/237/head
João Matos 11 years ago
parent
commit
20bd612ced
  1. 79
      include/CppSharp.h
  2. 5
      src/Generator/Generators/CLI/CLITypePrinter.cs
  3. 5
      src/Generator/Types/ITypePrinter.cs
  4. 40
      src/Generator/Types/Std/Stdlib.cs
  5. 46
      tests/STL/STL.Tests.cs
  6. 11
      tests/STL/STL.cpp
  7. 1
      tests/STL/STL.cs
  8. 29
      tests/STL/STL.h

79
include/CppSharp.h

@ -9,7 +9,9 @@
#pragma once #pragma once
#include <string> #include <string>
#include <ostream>
#include <vcclr.h> #include <vcclr.h>
#include <msclr/marshal.h>
public interface class ICppInstance public interface class ICppInstance
{ {
@ -212,3 +214,80 @@ namespace clix {
} }
} // 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<System::IO::TextWriter^> & 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<System::IO::TextWriter^> m_tw;
};
class text_writer_ostream : public std::ostream {
public:
text_writer_ostream(const gcroot<System::IO::TextWriter^> & s) :
std::ios(),
std::ostream(0),
m_sbuf(s)
{
init(&m_sbuf);
}
private:
text_writer_streambuf m_sbuf;
};
}
template<>
ref class context_node<std::ostream*, System::IO::TextWriter^> : 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

5
src/Generator/Generators/CLI/CLITypePrinter.cs

@ -284,7 +284,10 @@ namespace CppSharp.Generators.CLI
public string VisitCILType(CILType type, TypeQualifiers quals) public string VisitCILType(CILType type, TypeQualifiers quals)
{ {
return type.Type.FullName.Replace(".", "::") + "^"; var result = type.Type.FullName.Replace(".", "::");
if (!type.Type.IsValueType)
result += "^";
return result;
} }
public string VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals) public string VisitPrimitiveType(PrimitiveType type, TypeQualifiers quals)

5
src/Generator/Types/ITypePrinter.cs

@ -39,7 +39,10 @@ namespace CppSharp.Types
{ {
if (arg.Kind != TemplateArgument.ArgumentKind.Type) if (arg.Kind != TemplateArgument.ArgumentKind.Type)
continue; continue;
paramsList.Add(arg.Type.ToString()); var argType = arg.Type.Type.IsPointerToPrimitiveType()
? new CILType(typeof(System.IntPtr))
: arg.Type.Type;
paramsList.Add(argType.ToString());
} }
} }

40
src/Generator/Types/Std/Stdlib.cs

@ -1,4 +1,5 @@
using CppSharp.AST; using CppSharp.AST;
using CppSharp.AST.Extensions;
using CppSharp.Generators; using CppSharp.Generators;
using CppSharp.Generators.CLI; using CppSharp.Generators.CLI;
using CppSharp.Generators.CSharp; using CppSharp.Generators.CSharp;
@ -113,6 +114,10 @@ namespace CppSharp.Types.Std
{ {
var templateType = Type as TemplateSpecializationType; var templateType = Type as TemplateSpecializationType;
var type = templateType.Arguments[0].Type; var type = templateType.Arguments[0].Type;
var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType();
var managedType = isPointerToPrimitive
? new CILType(typeof(System.IntPtr))
: type.Type;
var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name var entryString = (ctx.Parameter != null) ? ctx.Parameter.Name
: ctx.ArgName; : ctx.ArgName;
@ -125,7 +130,7 @@ namespace CppSharp.Types.Std
ctx.SupportBefore.WriteLine("auto {0} = std::vector<{1}>();", ctx.SupportBefore.WriteLine("auto {0} = std::vector<{1}>();",
tmpVarName, nativeType); tmpVarName, nativeType);
ctx.SupportBefore.WriteLine("for each({0} _element in {1})", ctx.SupportBefore.WriteLine("for each({0} _element in {1})",
type.ToString(), entryString); managedType, entryString);
ctx.SupportBefore.WriteStartBraceIndent(); ctx.SupportBefore.WriteStartBraceIndent();
{ {
var param = new Parameter var param = new Parameter
@ -146,6 +151,10 @@ namespace CppSharp.Types.Std
if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore)) if (!string.IsNullOrWhiteSpace(marshal.Context.SupportBefore))
ctx.SupportBefore.Write(marshal.Context.SupportBefore); ctx.SupportBefore.Write(marshal.Context.SupportBefore);
if (isPointerToPrimitive)
ctx.SupportBefore.WriteLine("auto _marshalElement = {0}.ToPointer();",
marshal.Context.Return);
else
ctx.SupportBefore.WriteLine("auto _marshalElement = {0};", ctx.SupportBefore.WriteLine("auto _marshalElement = {0};",
marshal.Context.Return); marshal.Context.Return);
@ -162,11 +171,15 @@ namespace CppSharp.Types.Std
{ {
var templateType = Type as TemplateSpecializationType; var templateType = Type as TemplateSpecializationType;
var type = templateType.Arguments[0].Type; var type = templateType.Arguments[0].Type;
var isPointerToPrimitive = type.Type.IsPointerToPrimitiveType();
var managedType = isPointerToPrimitive
? new CILType(typeof(System.IntPtr))
: type.Type;
var tmpVarName = "_tmp" + ctx.ArgName; var tmpVarName = "_tmp" + ctx.ArgName;
ctx.SupportBefore.WriteLine( ctx.SupportBefore.WriteLine(
"auto {0} = gcnew System::Collections::Generic::List<{1}>();", "auto {0} = gcnew System::Collections::Generic::List<{1}>();",
tmpVarName, type.ToString()); tmpVarName, managedType);
ctx.SupportBefore.WriteLine("for(auto _element : {0})", ctx.SupportBefore.WriteLine("for(auto _element : {0})",
ctx.ReturnVarName); ctx.ReturnVarName);
ctx.SupportBefore.WriteStartBraceIndent(); ctx.SupportBefore.WriteStartBraceIndent();
@ -186,6 +199,10 @@ namespace CppSharp.Types.Std
ctx.SupportBefore.WriteLine("auto _marshalElement = {0};", ctx.SupportBefore.WriteLine("auto _marshalElement = {0};",
marshal.Context.Return); marshal.Context.Return);
if (isPointerToPrimitive)
ctx.SupportBefore.WriteLine("{0}->Add({1}(_marshalElement));",
tmpVarName, managedType);
else
ctx.SupportBefore.WriteLine("{0}->Add(_marshalElement);", ctx.SupportBefore.WriteLine("{0}->Add(_marshalElement);",
tmpVarName); tmpVarName);
} }
@ -276,4 +293,23 @@ namespace CppSharp.Types.Std
throw new System.NotImplementedException(); 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<std::ostream*>({1})",
marshalCtxName, ctx.Parameter.Name);
}
}
} }

46
tests/STL/STL.Tests.cs

@ -1,7 +1,10 @@
using System.Collections.Generic; using CppSharp.Utils;
using System.Linq;
using CppSharp.Utils;
using NUnit.Framework; using NUnit.Framework;
using STL;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
public class STLTests : GeneratorTestFixture public class STLTests : GeneratorTestFixture
{ {
@ -15,6 +18,43 @@ public class STLTests : GeneratorTestFixture
var list = vectors.GetIntVector(); var list = vectors.GetIntVector();
Assert.True(list.SequenceEqual(new List<int> { 2, 3, 4 })); Assert.True(list.SequenceEqual(new List<int> { 2, 3, 4 }));
var ptrList = vectors.IntPtrVector;
var intList = ptrList.Select(ptr => Marshal.ReadInt32(ptr));
Assert.True(intList.SequenceEqual(new List<int> { 2, 3, 4 }));
var wrapperList = new List<IntWrapper>();
for (int i = 0; i < 3; i++)
wrapperList.Add(new IntWrapper() { Value = i });
vectors.IntWrapperVector = wrapperList;
wrapperList = vectors.IntWrapperVector;
for (int i = 0; i < 3; i++)
Assert.AreEqual(i, wrapperList[i].Value);
for (int i = 0; i < 3; i++)
wrapperList[i].Value += i;
vectors.IntWrapperPtrVector = wrapperList;
wrapperList = vectors.IntWrapperPtrVector;
for (int i = 0; i < 3; i++)
Assert.AreEqual(i * 2, wrapperList[i].Value);
var valueTypeWrapperList = new List<IntWrapperValueType>();
for (int i = 0; i < 3; i++)
valueTypeWrapperList.Add(new IntWrapperValueType() { Value = i });
vectors.IntWrapperValueTypeVector = valueTypeWrapperList;
valueTypeWrapperList = vectors.IntWrapperValueTypeVector;
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());
} }
} }

11
tests/STL/STL.cpp

@ -1,5 +1,16 @@
#include "STL.h" #include "STL.h"
TestVectors::TestVectors()
{
IntVector.push_back(2);
IntVector.push_back(3);
IntVector.push_back(4);
IntPtrVector.push_back(&IntVector[0]);
IntPtrVector.push_back(&IntVector[1]);
IntPtrVector.push_back(&IntVector[2]);
}
std::vector<int> TestVectors::GetIntVector() std::vector<int> TestVectors::GetIntVector()
{ {
std::vector<int> vec; std::vector<int> vec;

1
tests/STL/STL.cs

@ -13,6 +13,7 @@ namespace CppSharp.Tests
public override void Preprocess(Driver driver, ASTContext ctx) public override void Preprocess(Driver driver, ASTContext ctx)
{ {
ctx.SetClassAsValueType("IntWrapperValueType");
} }
public static void Main(string[] args) public static void Main(string[] args)

29
tests/STL/STL.h

@ -1,10 +1,39 @@
#include "../Tests.h" #include "../Tests.h"
#include <vector> #include <vector>
#include <ostream>
struct DLL_API IntWrapper
{
int Value;
};
struct DLL_API IntWrapperValueType
{
int Value;
};
struct DLL_API TestVectors struct DLL_API TestVectors
{ {
TestVectors();
std::vector<int> GetIntVector(); std::vector<int> GetIntVector();
int SumIntVector(std::vector<int>& vec); int SumIntVector(std::vector<int>& vec);
// Should get mapped to List<int>
std::vector<int> IntVector; std::vector<int> IntVector;
// Should get mapped to List<IntPtr>
std::vector<int*> IntPtrVector;
// Should get mapped to List<IntWrapper>
std::vector<IntWrapper> IntWrapperVector;
// Should get mapped to List<IntWrapper>
std::vector<IntWrapper*> IntWrapperPtrVector;
// Should get mapped to List<IntWrapperValueType>
std::vector<IntWrapperValueType> IntWrapperValueTypeVector;
};
struct DLL_API OStreamTest
{
static void WriteToOStream(std::ostream& stream, const char* s)
{
stream << s;
};
}; };
Loading…
Cancel
Save