diff --git a/Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.CPtrInterop_architecture=Wide.verified.txt b/Cesium.CodeGen.Tests/verified/CodeGenNetInteropTests.CPtrInterop_architecture=Wide.verified.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/Cesium.CodeGen/Contexts/AssemblyContext.cs b/Cesium.CodeGen/Contexts/AssemblyContext.cs index e3883c39..cd880f89 100644 --- a/Cesium.CodeGen/Contexts/AssemblyContext.cs +++ b/Cesium.CodeGen/Contexts/AssemblyContext.cs @@ -77,6 +77,9 @@ public AssemblyDefinition VerifyAndGetAssembly() private MethodDefinition? _globalInitializer; private readonly TypeReference _runtimeCPtr; + private readonly Lazy _cPtrConverter; + public MethodReference CPtrConverter => _cPtrConverter.Value; + public TypeReference RuntimeVoidPtr { get; } private readonly TypeReference _runtimeFuncPtr; @@ -136,11 +139,15 @@ TypeDefinition GetRuntimeType(string typeName) => _importedActionDelegates = new("System", "Action", Module); _importedFuncDelegates = new("System", "Func", Module); - _voidPtrConverter = new(() => + _voidPtrConverter = new(() => GetImplicitCastOperator(TypeSystemEx.VoidPtrFullTypeName)); + _cPtrConverter = new(() => throw new WipException(WipException.ToDo, "TODO: Make the cast operators specialized by types, introduce a cache or something.")); + return; + + MethodReference GetImplicitCastOperator(string typeName) { - var voidPtrType = GetRuntimeType(TypeSystemEx.VoidPtrFullTypeName); - return Module.ImportReference(voidPtrType.Methods.Single(m => m.Name == "op_Implicit")); - }); + var type = GetRuntimeType(typeName); + return Module.ImportReference(type.Methods.Single(m => m.Name == "op_Implicit")); + } } public TypeReference RuntimeCPtr(TypeReference typeReference) diff --git a/Cesium.CodeGen/Ir/Expressions/TypeCastExpression.cs b/Cesium.CodeGen/Ir/Expressions/TypeCastExpression.cs index 2d9bbca6..2ebcc0c4 100644 --- a/Cesium.CodeGen/Ir/Expressions/TypeCastExpression.cs +++ b/Cesium.CodeGen/Ir/Expressions/TypeCastExpression.cs @@ -58,7 +58,9 @@ public void EmitTo(IEmitScope scope) Add(OpCodes.Conv_I); else if (TargetType is InteropType iType) { - if (iType.UnderlyingType.FullName == TypeSystemEx.VoidPtrFullTypeName) + var type = iType.UnderlyingType; + if (type.FullName == TypeSystemEx.VoidPtrFullTypeName + || type.IsGenericInstance && type.GetElementType().FullName == TypeSystemEx.CPtrFullTypeName) { Add(OpCodes.Conv_I); // TODO: Should only emit if required. scope.Method.Body.Instructions.Add( diff --git a/Cesium.CodeGen/Ir/Types/InteropType.cs b/Cesium.CodeGen/Ir/Types/InteropType.cs index 40cd2a92..acf228bf 100644 --- a/Cesium.CodeGen/Ir/Types/InteropType.cs +++ b/Cesium.CodeGen/Ir/Types/InteropType.cs @@ -40,8 +40,10 @@ public MethodReference GetConvertCall(AssemblyContext context) if (UnderlyingType.IsGenericInstance) { var parent = UnderlyingType.GetElementType(); + if (parent.FullName == TypeSystemEx.CPtrFullTypeName) + return context.CPtrConverter; - throw new WipException(WipException.ToDo, "Cannot import converter methods for CPtr or FuncPtr, yet."); + throw new WipException(WipException.ToDo, "Cannot import the converter method for FuncPtr, yet."); } throw new AssertException(