C # /. NET Generics и Cdecl Varargs Ошибка? - PullRequest
5 голосов
/ 01 мая 2011

Почему 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)); }
}

Ответы [ 3 ]

0 голосов
/ 01 мая 2011

Вы спрашиваете, почему не работает недокументированное (_ arglist, _makeref, _ reftype, _refvalue) ключевое слово.

Что ж, вы должны спросить Microsoft: D

Если вы действительно хотите узнать мое мнение об этом, это может быть из-за того, что генерики не знают тип T во время компиляции, и все же они скомпилированы в классы.Что __arglist берет во время компиляции, есть загадка.Поскольку в строке, где вы объявляете универсальный тип, не указывайте тип параметра для __arglist.

Но все это так же неясно, как использование sprintf из C # ... по крайней мере, если бы это был _snwprintf_s или аналогичный: D

0 голосов
/ 21 июля 2014

Как показано в следующем коде, исключение выдается перед запуском метода, когда он компилируется в собственный код:

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, которая заставляет его передавать внутренний дескриптор параметру универсального типа вместо дескриптора реального типа, передаваемого методу.

0 голосов
/ 01 мая 2011

Попробуй так:

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); }
}
...