Browse Source

Fixed the generated C# for indexers in templates.

Signed-off-by: Dimitar Dobrev <dpldobrev@protonmail.com>
pull/890/head
Dimitar Dobrev 9 years ago
parent
commit
e078968cf2
  1. 19
      src/Generator/Generators/CSharp/CSharpMarshal.cs
  2. 34
      src/Generator/Generators/CSharp/CSharpSources.cs
  3. 3
      src/Generator/Passes/SpecializationMethodsWithDependentPointersPass.cs
  4. 25
      tests/CSharp/CSharp.Tests.cs
  5. 33
      tests/CSharp/CSharpTemplates.h

19
src/Generator/Generators/CSharp/CSharpMarshal.cs

@ -167,12 +167,23 @@ namespace CppSharp.Generators.CSharp
return true; return true;
} }
if (Context.Context.Options.MarshalCharAsManagedChar && primitive == PrimitiveType.Char) if (Context.Context.Options.MarshalCharAsManagedChar &&
Context.Return.Write(string.Format("({0}) ", pointer)); primitive == PrimitiveType.Char)
Context.Return.Write($"({pointer}) ");
var type = Context.ReturnType.Type.Desugar(
resolveTemplateSubstitution: false);
if (Context.Function != null && if (Context.Function != null &&
Context.Function.OperatorKind == CXXOperatorKind.Subscript && Context.Function.OperatorKind == CXXOperatorKind.Subscript &&
Context.ReturnType.Type.Desugar().IsPrimitiveType(primitive)) type.IsPrimitiveType(primitive))
{
var substitute = type as TemplateParameterSubstitutionType;
if (substitute != null)
Context.Return.Write($@"({
substitute.ReplacedParameter.Parameter.Name}) (object) ");
Context.Return.Write("*"); Context.Return.Write("*");
}
Context.Return.Write(Context.ReturnVarName); Context.Return.Write(Context.ReturnVarName);
return true; return true;
} }
@ -732,7 +743,7 @@ namespace CppSharp.Generators.CSharp
} }
string param = Context.Parameter.Name; string param = Context.Parameter.Name;
Type type = Context.Parameter.Type.Desugar(false); Type type = Context.Parameter.Type.Desugar(resolveTemplateSubstitution: false);
string paramInstance; string paramInstance;
Class @interface; Class @interface;
var finalType = type.GetFinalPointee() ?? type; var finalType = type.GetFinalPointee() ?? type;

34
src/Generator/Generators/CSharp/CSharpSources.cs

@ -928,28 +928,36 @@ namespace CppSharp.Generators.CSharp
{ {
Type type; Type type;
function.Type.IsPointerTo(out type); function.Type.IsPointerTo(out type);
PrimitiveType primitiveType;
var @internal = TypePrinter.PrintNative(function.Namespace);
var ctx = new CSharpMarshalContext(Context)
{
Parameter = new Parameter
{
Name = "value",
QualifiedType = new QualifiedType(type)
},
ReturnType = new QualifiedType(type)
};
var marshal = new CSharpMarshalManagedToNativePrinter(ctx);
type.Visit(marshal);
Write(marshal.Context.Before);
var internalFunction = GetFunctionNativeIdentifier(function); var internalFunction = GetFunctionNativeIdentifier(function);
var @internal = $@"{Helpers.InternalStruct}{ if (type.IsPrimitiveType())
Helpers.GetSuffixForInternal(function.Namespace)}";
if (type.IsPrimitiveType(out primitiveType))
{ {
WriteLine($@"*{@internal}.{internalFunction}({ WriteLine($@"*{@internal}.{internalFunction}({
GetInstanceParam(function)}, {function.Parameters[0].Name}) = value;"); GetInstanceParam(function)}, {function.Parameters[0].Name}) = {
marshal.Context.Return};");
} }
else else
{ {
var typeString = type.ToString(); var typeInternal = TypePrinter.PrintNative(type);
Class @class;
var isValueType = (type.GetFinalPointee() ?? type).TryGetClass(out @class) &&
@class.IsValueType;
var paramMarshal = GenerateFunctionParamMarshal( var paramMarshal = GenerateFunctionParamMarshal(
function.Parameters[0], 0, function); function.Parameters[0], 0, function);
WriteLine($@"*({typeString}.{@internal}*) {@internal}.{internalFunction}({ WriteLine($@"*({typeInternal}*) {@internal}.{internalFunction}({
GetInstanceParam(function)}, {(paramMarshal.Context == null ? GetInstanceParam(function)}, {(paramMarshal.Context == null ?
paramMarshal.Name : paramMarshal.Context.Return)}) = { paramMarshal.Name : paramMarshal.Context.Return)}) = {marshal.Context.Return};");
(isValueType ? string.Empty : $@"*({typeString}.{@internal}*) ")}value.{
Helpers.InstanceIdentifier};");
} }
} }

3
src/Generator/Passes/SpecializationMethodsWithDependentPointersPass.cs

@ -146,7 +146,8 @@ namespace CppSharp.Passes
var type = qualType.Type.Desugar(); var type = qualType.Type.Desugar();
while (type.IsAddress()) while (type.IsAddress())
{ {
var pointee = ((PointerType) type).Pointee.Desugar(false); var pointee = ((PointerType) type).Pointee.Desugar(
resolveTemplateSubstitution: false);
if (pointee.IsAddress()) if (pointee.IsAddress())
type = pointee; type = pointee;
else else

25
tests/CSharp/CSharp.Tests.cs

@ -739,6 +739,31 @@ public unsafe class CSharpTests : GeneratorTestFixture
Assert.That(IndependentFields<T1>.IndependentConst, Is.EqualTo(15)); Assert.That(IndependentFields<T1>.IndependentConst, Is.EqualTo(15));
} }
[Test]
public void TestTemplateWithIndexer()
{
using (var templateWithIndexer = new TemplateWithIndexer<int>())
{
templateWithIndexer[0] = 5;
Assert.That(templateWithIndexer[0], Is.EqualTo(5));
templateWithIndexer["test"] = 15;
Assert.That(templateWithIndexer["test"], Is.EqualTo(15));
}
using (var templateWithIndexer = new TemplateWithIndexer<T1>())
{
using (var t1 = new T1(10))
{
templateWithIndexer[0] = t1;
Assert.That(templateWithIndexer[0].Field, Is.EqualTo(t1.Field));
}
using (var t1 = new T1(15))
{
templateWithIndexer["test"] = t1;
Assert.That(templateWithIndexer["test"].Field, Is.EqualTo(t1.Field));
}
}
}
[Test] [Test]
public void TestAbstractImplementatonsInPrimaryAndSecondaryBases() public void TestAbstractImplementatonsInPrimaryAndSecondaryBases()
{ {

33
tests/CSharp/CSharpTemplates.h

@ -152,6 +152,34 @@ private:
static bool staticField; static bool staticField;
}; };
template <typename T>
class TemplateWithIndexer
{
public:
TemplateWithIndexer();
T& operator[](int i);
T& operator[](const char* string);
private:
T t[1];
};
template <typename T>
TemplateWithIndexer<T>::TemplateWithIndexer()
{
}
template <typename T>
T& TemplateWithIndexer<T>::operator[](int i)
{
return t[0];
}
template <typename T>
T& TemplateWithIndexer<T>::operator[](const char* string)
{
return t[0];
}
template <typename T, typename D> template <typename T, typename D>
HasDefaultTemplateArgument<T, D>::HasDefaultTemplateArgument() HasDefaultTemplateArgument<T, D>::HasDefaultTemplateArgument()
{ {
@ -307,7 +335,8 @@ struct MapResultType<InputSequence<T>, MapFunctor>
void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool> _2, void forceUseSpecializations(IndependentFields<int> _1, IndependentFields<bool> _2,
IndependentFields<T1> _3, IndependentFields<std::string> _4, IndependentFields<T1> _3, IndependentFields<std::string> _4,
VirtualTemplate<int> _5, VirtualTemplate<bool> _6, VirtualTemplate<int> _5, VirtualTemplate<bool> _6,
HasDefaultTemplateArgument<int, int> _7, DerivedChangesTypeName<T1> _8, std::string s); HasDefaultTemplateArgument<int, int> _7, DerivedChangesTypeName<T1> _8,
TemplateWithIndexer<int> _9, TemplateWithIndexer<T1> _10, std::string s);
// force the symbols for the template instantiations because we do not have the auto-compilation for the generated C++ source // force the symbols for the template instantiations because we do not have the auto-compilation for the generated C++ source
template class DLL_API IndependentFields<int>; template class DLL_API IndependentFields<int>;
@ -318,3 +347,5 @@ template class DLL_API VirtualTemplate<int>;
template class DLL_API VirtualTemplate<bool>; template class DLL_API VirtualTemplate<bool>;
template class DLL_API HasDefaultTemplateArgument<int, int>; template class DLL_API HasDefaultTemplateArgument<int, int>;
template class DLL_API DerivedChangesTypeName<T1>; template class DLL_API DerivedChangesTypeName<T1>;
template class DLL_API TemplateWithIndexer<int>;
template class DLL_API TemplateWithIndexer<T1>;

Loading…
Cancel
Save