private static void EmitStringArrayEpilogue(MethodDefinition wrapper, ParameterDefinition parameter, MethodBody body, ILProcessor il, GeneratedVariableIdentifier generatedPtrVar) { if (generatedPtrVar == null) { throw new ArgumentNullException(nameof(generatedPtrVar)); } // Note: only works for string vectors (1d arrays). // We do not (and will probably never) support 2d or higher string arrays var free = wrapper.Module.ImportReference(TypeBindingsBase.Methods.First(m => m.Name == "FreeStringArrayPtr")); // FreeStringArrayPtr(string_array_ptr, string_array.Length) // load string_array_ptr il.Emit(OpCodes.Ldloc, generatedPtrVar.Definition.Index); // load string_array.Length il.Emit(OpCodes.Ldarg, parameter.Index); il.Emit(OpCodes.Ldlen); il.Emit(OpCodes.Conv_I4); // call FreeStringArrayPtr il.Emit(OpCodes.Call, free); }
private static GeneratedVariableIdentifier EmitStringArrayParameter(MethodDefinition wrapper, ParameterDefinition parameter, MethodBody body, ILProcessor il) { // string[] masrhaling: // IntPtr ptr = MarshalStringArrayToPtr(strings); // try { calli } // finally { FreeStringArrayPtr(ptr); } var marshal_str_array_to_ptr = wrapper.Module.ImportReference(TypeBindingsBase.Methods.First(m => m.Name == "MarshalStringArrayToPtr")); // IntPtr ptr; var variableDefinition = new VariableDefinition(TypeIntPtr); body.Variables.Add(variableDefinition); int generatedPointerVarIndex = body.Variables.Count - 1; GeneratedVariableIdentifier stringArrayPtrVar = new GeneratedVariableIdentifier(body, variableDefinition, parameter.Name + "_string_array_ptr"); // ptr = MarshalStringArrayToPtr(strings); il.Emit(OpCodes.Call, marshal_str_array_to_ptr); il.Emit(OpCodes.Stloc, generatedPointerVarIndex); il.Emit(OpCodes.Ldloc, generatedPointerVarIndex); // The finally block will be emitted in the function epilogue return(stringArrayPtrVar); }
private static void EmitStringEpilogue(MethodDefinition wrapper, ParameterDefinition parameter, MethodBody body, ILProcessor il, GeneratedVariableIdentifier generatedPtrVar) { var free = wrapper.Module.ImportReference(TypeBindingsBase.Methods.First(m => m.Name == "FreeStringPtr")); // FreeStringPtr(ptr) il.Emit(OpCodes.Ldloc, generatedPtrVar.Definition.Index); il.Emit(OpCodes.Call, free); }
private static void EmitStringOutEpilogue(MethodDefinition wrapper, MethodDefinition native, ParameterDefinition parameter, MethodBody body, ILProcessor il, GeneratedVariableIdentifier generatedPtrVar) { if (generatedPtrVar == null) { throw new ArgumentNullException(nameof(generatedPtrVar)); } // void GetShaderInfoLog(..., out String foo) // IntPtr foo_string_ptr; // try { // foo_string_ptr = Marshal.AllocHGlobal(count + 1); // glGetShaderInfoLog(..., foo_string_ptr); // foo = MarshalPtrToString(foo_string_ptr); // } // finally { // Marshal.FreeHGlobal(foo_string_ptr); // } // Make sure we have imported BindingsBase::MasrhalPtrToString and Marshal::FreeHGlobal var ptr_to_str = wrapper.Module.ImportReference(TypeBindingsBase.Methods.First(m => m.Name == "MarshalPtrToString")); var free_hglobal = wrapper.Module.ImportReference(TypeMarshal.Methods.First(m => m.Name == "FreeHGlobal")); var block = new ExceptionHandler(ExceptionHandlerType.Finally); block.TryStart = body.Instructions[0]; il.Emit(OpCodes.Ldarg, parameter.Index); il.Emit(OpCodes.Ldloc, generatedPtrVar.Definition.Index); il.Emit(OpCodes.Call, ptr_to_str); il.Emit(OpCodes.Stind_Ref); block.TryEnd = body.Instructions.Last(); block.HandlerStart = body.Instructions.Last(); il.Emit(OpCodes.Ldloc, generatedPtrVar.Definition.Index); il.Emit(OpCodes.Call, free_hglobal); block.HandlerEnd = body.Instructions.Last(); }
private static GeneratedVariableIdentifier EmitStringOutParameter(MethodDefinition method, ParameterDefinition parameter, MethodBody body, ILProcessor il) { // void GetShaderInfoLog(..., out String foo) // IntPtr foo_string_ptr; // try { // foo_string_ptr = Marshal.AllocHGlobal(count + 1); // glGetShaderInfoLog(..., foo_string_ptr); // foo = MarshalPtrToString(foo_string_ptr); // } // finally { // Marshal.FreeHGlobal(foo_string_ptr); // } // Pop off the string parameter that would of just been loaded il.Emit(OpCodes.Pop); // Make sure we have imported Marshal::AllocHGlobal var alloc_hglobal = method.Module.ImportReference(TypeMarshal.Methods.First(m => m.Name == "AllocHGlobal")); // IntPtr ptr; var variableDefinition = new VariableDefinition(TypeIntPtr); body.Variables.Add(variableDefinition); int stringPtrIndex = body.Variables.Count - 1; GeneratedVariableIdentifier stringPtrVar = new GeneratedVariableIdentifier(body, variableDefinition, parameter.Name + "_string_ptr"); // ptr = Marshal.AllocHGlobal(count + 1); var count = GetCountAttribute(parameter); if (count == null) { // We need a count attribute so we know what size to make the // string buffer. Currently every string out parameter has a // count attribute but this check is in place to make things // clearer if this case is ever hit. throw new InvalidOperationException(string.Format("{0}({1}) doesn't have a count attribute", method.Name, parameter.Name)); } if (count.Count != 0) { // Fixed size il.Emit(OpCodes.Ldc_I4, count.Count); } else if (count.Parameter != null) { // Parameter sized var countVariable = EmitCountVariable(method, body, il, count.Parameter); il.Emit(OpCodes.Ldloc, countVariable.Index); } else if (count.Computed != null) { if (method.Name == "GetActiveVarying") { // GetActiveVaryingNV's name parameter has a count of "COMPSIZE(program,index,bufSize)" but really it should be bufSize. var countVariable = EmitCountVariable(method, body, il, "bufSize"); il.Emit(OpCodes.Ldloc, countVariable.Index); } else { // Computed counts are hard and require manual reading of the specification for each one. throw new NotSupportedException(string.Format("{0}({1}) requires a computed count: {2}", method.Name, parameter.Name, count.Computed)); } } il.Emit(OpCodes.Ldc_I4, 1); il.Emit(OpCodes.Add); il.Emit(OpCodes.Call, alloc_hglobal); il.Emit(OpCodes.Stloc, stringPtrIndex); il.Emit(OpCodes.Ldloc, stringPtrIndex); // We'll emit the try-finally block in the epilogue implementation, // because we haven't yet emitted all necessary instructions here. return(stringPtrVar); }