C#/.NET 泛型和 Cdecl Varargs 错误?

发布于 2024-11-04 11:46:44 字数 690 浏览 3 评论 0原文

为什么 Foo() 成功,但 Bar() 抛出 BadImageFormatException

using System.Runtime.InteropServices;
using System.Text;

static class Program
{
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int sprintf([Out] StringBuilder buf, string format, __arglist);

    static void Main(string[] args)
    {
        Foo<int>(2); //Runs fine
        Bar<int>(2); //Error: "The signature is incorrect"
    }

 static void Foo<T>(int a) { sprintf(new StringBuilder(8), "%d", __arglist(a)); }
 static void Bar<T>(T   a) { sprintf(new StringBuilder(8), "%d", __arglist(a)); }
}

Why does Foo() succeed but Bar() throws a BadImageFormatException?

using System.Runtime.InteropServices;
using System.Text;

static class Program
{
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int sprintf([Out] StringBuilder buf, string format, __arglist);

    static void Main(string[] args)
    {
        Foo<int>(2); //Runs fine
        Bar<int>(2); //Error: "The signature is incorrect"
    }

 static void Foo<T>(int a) { sprintf(new StringBuilder(8), "%d", __arglist(a)); }
 static void Bar<T>(T   a) { sprintf(new StringBuilder(8), "%d", __arglist(a)); }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

始于初秋 2024-11-11 11:46:44

尝试这样:

using System;
using System.Runtime.InteropServices;
using System.Text;

static class Program
{
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int sprintf([Out] StringBuilder buf, string format, params object[] args);

    static void Main(string[] args)
    {
        Foo(2);
        Bar<int>(2);
    }

    static void Foo(int a) { sprintf(new StringBuilder(8), "%d", a); }
    static void Bar<T>(T a){ sprintf(new StringBuilder(8), "%d", a); }
}

Try like this:

using System;
using System.Runtime.InteropServices;
using System.Text;

static class Program
{
    [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
    static extern int sprintf([Out] StringBuilder buf, string format, params object[] args);

    static void Main(string[] args)
    {
        Foo(2);
        Bar<int>(2);
    }

    static void Foo(int a) { sprintf(new StringBuilder(8), "%d", a); }
    static void Bar<T>(T a){ sprintf(new StringBuilder(8), "%d", a); }
}
橘亓 2024-11-11 11:46:44

您问为什么未记录的(_arglist、_makeref、_reftype、_refvalue)关键字不起作用。

好吧,你应该问 Microsoft:D

如果你真的想知道我对此的看法,可能是因为泛型在编译时不知道 T 的类型,但它们被编译为类。 __arglist 在编译时采用什么是一个谜。因为在声明泛型的行中没有指定 __arglist 的参数类型。

但所有这些都像在 C# 中使用 sprintf 一样晦涩难懂...至少如果它是 _snwprintf_s 或类似的:D

You are asking why an undocumented (_arglist,_makeref,_reftype,_refvalue) keyword does not work.

Well you should ask Microsoft :D

If you really want to know my take on this, it could be because generics don't know the type of T at compile time, and yet they are compiled to classes. What does __arglist take at compilation time there is a mystery. Since in the line where you declare the generic don't specify the kind of parameter to __arglist.

But all of this is as much obscure as using sprintf from C#... at least if it were _snwprintf_s or similar :D

故笙诉离歌 2024-11-11 11:46:44

如下面的代码所示,当该方法被编译为本机代码时,在运行该方法之前会抛出异常:

var t = typeof(Program);
var m = t.GetMethod("Bar", BindingFlags.NonPublic | BindingFlags.Static);
m = m.MakeGenericMethod(typeof(int));
System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(m.MethodHandle); //error

此外,它还抱怨传递给 SizeOf 的类型错误。我猜想这可能是 CLR 中的一个错误,导致它将内部句柄传递给泛型类型参数,而不是传递给方法的真实类型的句柄。

As shown in the following code, the exception is thrown before running the method when it is compiled into native code:

var t = typeof(Program);
var m = t.GetMethod("Bar", BindingFlags.NonPublic | BindingFlags.Static);
m = m.MakeGenericMethod(typeof(int));
System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(m.MethodHandle); //error

Also it is complaining about wrong type passed to SizeOf. I guess it might be a bug in the CLR that causes it to pass the internal handle to the generic type parameter instead of the handle of the real type passed to the method.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文