Browse Source

Fixed the C# generation for functions with typedefed function pointers as params (#903)

pull/890/head
Mohit Mohta 8 years ago committed by Dimitar Dobrev
parent
commit
db522c0295
  1. 4
      src/Generator/BindingContext.cs
  2. 3
      src/Generator/Generators/CSharp/CSharpTypePrinter.cs
  3. 83
      src/Generator/Passes/DelegatesPass.cs
  4. 8
      tests/CSharp/CSharp.Tests.cs
  5. 7
      tests/CSharp/CSharp.cpp
  6. 3
      tests/CSharp/CSharp.h

4
src/Generator/BindingContext.cs

@ -20,7 +20,7 @@ namespace CppSharp.Generators @@ -20,7 +20,7 @@ namespace CppSharp.Generators
public PassBuilder<TranslationUnitPass> TranslationUnitPasses { get; private set; }
public PassBuilder<GeneratorOutputPass> GeneratorOutputPasses { get; private set; }
public Dictionary<Function, DelegatesPass.DelegateDefinition> Delegates { get; private set; }
public Dictionary<Declaration, DelegatesPass.DelegateDefinition> Delegates { get; private set; }
public BindingContext(DriverOptions options, ParserOptions parserOptions = null)
{
@ -28,7 +28,7 @@ namespace CppSharp.Generators @@ -28,7 +28,7 @@ namespace CppSharp.Generators
ParserOptions = parserOptions;
Symbols = new SymbolContext();
Delegates = new Dictionary<Function, DelegatesPass.DelegateDefinition>();
Delegates = new Dictionary<Declaration, DelegatesPass.DelegateDefinition>();
TypeMaps = new TypeMapDatabase();

3
src/Generator/Generators/CSharp/CSharpTypePrinter.cs

@ -655,6 +655,9 @@ namespace CppSharp.Generators.CSharp @@ -655,6 +655,9 @@ namespace CppSharp.Generators.CSharp
typeBuilder.Append(printedType.NameSuffix);
var type = typeBuilder.ToString();
if (Context.Delegates.ContainsKey(param))
return $"{Context.Delegates[param].Signature} {param.Name}";
if (ContextKind == TypePrinterContextKind.Native)
return $"{type} {param.Name}";

83
src/Generator/Passes/DelegatesPass.cs

@ -53,17 +53,33 @@ namespace CppSharp.Passes @@ -53,17 +53,33 @@ namespace CppSharp.Passes
return result;
}
public override bool VisitMethodDecl(Method method)
private void AddDelegatesToDictionary(Declaration decl, Module module)
{
if (!base.VisitMethodDecl(method) || !method.IsVirtual || method.Ignore)
return false;
var @params = method.GatherInternalParams(Context.ParserOptions.IsItaniumLikeAbi, true).ToList();
var delegateName = GenerateDelegateSignature(@params, method.ReturnType);
var module = method.TranslationUnit.Module;
CallingConvention callingConvention;
bool isDependent = false;
QualifiedType returnType;
List<Parameter> @params;
if (decl is Method)
{
var method = (Method) decl;
@params = method.GatherInternalParams(Context.ParserOptions.IsItaniumLikeAbi, true).ToList();
callingConvention = method.CallingConvention;
isDependent = method.IsDependent;
returnType = method.ReturnType;
}
else
{
var param = (Parameter) decl;
var funcTypeParam = param.Type.Desugar().GetFinalPointee().Desugar() as FunctionType;
@params = funcTypeParam.Parameters;
callingConvention = funcTypeParam.CallingConvention;
isDependent = funcTypeParam.IsDependent;
returnType = funcTypeParam.ReturnType;
}
var delegateName = GenerateDelegateSignature(@params, returnType);
Namespace namespaceDelegates;
if (namespacesDelegates.ContainsKey(module))
{
namespaceDelegates = namespacesDelegates[module];
@ -96,32 +112,67 @@ namespace CppSharp.Passes @@ -96,32 +112,67 @@ namespace CppSharp.Passes
new QualifiedType(
new FunctionType
{
CallingConvention = method.CallingConvention,
IsDependent = method.IsDependent,
CallingConvention = callingConvention,
IsDependent = isDependent,
Parameters = @params,
ReturnType = method.ReturnType
ReturnType = returnType
}))),
Namespace = namespaceDelegates,
IsSynthetized = true,
Access = AccessSpecifier.Private
Access = decl is Method ? AccessSpecifier.Private : AccessSpecifier.Public
};
var delegateString = @delegate.Visit(TypePrinter).Type;
var existingDelegate = GetExistingDelegate(
method.TranslationUnit.Module, delegateString);
module, delegateString);
if (existingDelegate != null)
{
Context.Delegates.Add(method, existingDelegate);
return true;
Context.Delegates.Add(decl, existingDelegate);
return;
}
existingDelegate = new DelegateDefinition(module.OutputNamespace, delegateString);
Context.Delegates.Add(method, existingDelegate);
Context.Delegates.Add(decl, existingDelegate);
libsDelegates[module].Add(delegateString, existingDelegate);
namespaceDelegates.Declarations.Add(@delegate);
}
private void VisitFunctionTypeParameters(Function function)
{
foreach (var param in from param in function.Parameters
let paramType = param.Type.Desugar()
where paramType.IsAddress() &&
paramType.GetFinalPointee().Desugar() is FunctionType
select param)
{
var module = function.TranslationUnit.Module;
AddDelegatesToDictionary(param, module);
}
}
public override bool VisitFunctionDecl(Function function)
{
if (!base.VisitFunctionDecl(function) || function.Ignore)
return false;
// HACK : We should shift this call to VisitFunctionTypeParameters in VisitParameter. We can't do it now
// because we need to use the module and a since a parameter's namespace is null, we can't reach the
// translation unit and thus the module
VisitFunctionTypeParameters(function);
return true;
}
public override bool VisitMethodDecl(Method method)
{
if (!base.VisitMethodDecl(method) || !method.IsVirtual || method.Ignore)
return false;
var module = method.TranslationUnit.Module;
AddDelegatesToDictionary(method, module);
return true;
}

8
tests/CSharp/CSharp.Tests.cs

@ -5,6 +5,7 @@ using System.Runtime.InteropServices; @@ -5,6 +5,7 @@ using System.Runtime.InteropServices;
using CppSharp.Utils;
using CSharp;
using NUnit.Framework;
using CSharp.Delegates;
public unsafe class CSharpTests : GeneratorTestFixture
{
@ -854,4 +855,11 @@ public unsafe class CSharpTests : GeneratorTestFixture @@ -854,4 +855,11 @@ public unsafe class CSharpTests : GeneratorTestFixture
Assert.That(*((int*) indexproperty[n]), Is.EqualTo(21));
}
}
[Test, Platform(Exclude = "Win", Reason = "This test crashes our Windows build, possibly a problem with the NUnit runner there.")]
public void TestFuncWithTypedefedFuncPtrAsParam()
{
Func_int_IntPtr_CSharp_Bar___Internal function = (a, b) => 5;
Assert.That(CSharp.CSharp.FuncWithTypedefedFuncPtrAsParam(function), Is.EqualTo(5));
}
}

7
tests/CSharp/CSharp.cpp

@ -1354,3 +1354,10 @@ DLL_API int useDuplicateDeclaredStruct(DuplicateDeclaredStruct* s) @@ -1354,3 +1354,10 @@ DLL_API int useDuplicateDeclaredStruct(DuplicateDeclaredStruct* s)
void useStdStringJustAsParameter(std::string s)
{
}
int funcWithTypedefedFuncPtrAsParam(typedefedFuncPtr *func)
{
Foo* a = 0;
Bar b;
return func(a, b);
}

3
tests/CSharp/CSharp.h

@ -1217,3 +1217,6 @@ void* TestIndexedProperties::operator[](size_t n) const @@ -1217,3 +1217,6 @@ void* TestIndexedProperties::operator[](size_t n) const
extern const ComplexArrayElement ArrayOfVariableSize[];
void useStdStringJustAsParameter(std::string s);
typedef int (typedefedFuncPtr)(Foo *a, Bar b);
int DLL_API funcWithTypedefedFuncPtrAsParam(typedefedFuncPtr *func);

Loading…
Cancel
Save