【问题标题】:Calling varargs method via DynamicMethod通过 DynamicMethod 调用可变参数方法
【发布时间】:2015-04-05 15:00:53
【问题描述】:

我正在尝试使用 DynamicMethod 调用非托管的类似 printf 的函数。在运行时我得到一个

BadImageFormatException:找不到索引。 (HRESULT 的例外情况: 0x80131124)

这是运行时的限制还是我发出的代码有误?

public class Program
{
    [DllImport("msvcrt40.dll",CallingConvention = CallingConvention.Cdecl)]
    public static extern int printf(string format, __arglist);

    static void Main(string[] args) {

        var method = new DynamicMethod("printf", typeof(void), new Type[0], true);
        var il = method.GetILGenerator();

        il.Emit(OpCodes.Ldstr, " %s=%d\n");
        il.Emit(OpCodes.Ldstr, "a");
        il.Emit(OpCodes.Ldc_I4_0);
        il.EmitCall(OpCodes.Call, typeof(Program).GetMethod("printf", BindingFlags.Public | BindingFlags.Static), new Type[] { typeof(string), typeof(int) });
        il.Emit(OpCodes.Pop);
        il.Emit(OpCodes.Ret);

        var action = (Action)method.CreateDelegate(typeof(Action));
        action.Invoke();
    }
}

【问题讨论】:

  • 我将其与 C# 编译器生成的printf(" %s=%d\n", __arglist("a", 0)); 的 IL 进行了比较,并且哪个有效。除了maxstack 之外,它...与您的代码生成的完全相同。这很奇怪,它是相同的 IL,它应该工作相同。 ://
  • 如果我手动创建程序集、模块和类型(使用-Builder 类型)然后调用该方法,这实际上可以工作。很奇怪。

标签: c# .net-4.0 cil reflection.emit dynamicmethod


【解决方案1】:

虽然异常非常神秘,但我猜它是由于与调用 varargs 方法相关的一些安全检查而引发的,或者它可能是其中的错误。有效的是提供逻辑关联的类型或模块:

var method = new DynamicMethod("printf", typeof(void), new Type[0], typeof(Program), true);

然后完美运行。

【讨论】:

  • 确认,它有效。 doc“此外,可以跳过 JIT 可见性检查。”,看起来是相关的。
猜你喜欢
  • 1970-01-01
  • 2013-08-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多