Проблема структуры C# P/Invoke

Предложенное решение является излишне сложным. Бесчисленные переназначения переменных и цикл - рецепт головной боли. Вот упрощенная альтернатива -

def dual (f, g, n):
  if n == 0:
    return lambda x: x
  else:
    return lambda x: f(dual(g, f, n - 1)(x))

add1 = lambda x: 1 + x
add2 = lambda x: 2 + x

print(dual(add1,add2,4)(3))
# 9
# (1 + 2 + 1 + 2 + 3)

print(dual(add1,add2,9)(3))
# 16
# (1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 3)

print(dual(add1,add2,0)(3))
# 3

. Причина, по которой это работает, заключается в том, что в рекурсивной ветви мы называем dual с замененными аргументами, dual(g,f,n-1). Таким образом, f и g меняются местами каждый раз, когда n уменьшается до 0, базового случая, который возвращает функцию идентификации (без операции).

Немного менее читаемая версия, но работает идентично -

def dual (f, g, n):
  return lambda x: \
    x if n == 0 else f(dual(g, f, n - 1)(x))
6
задан Johnny Egeland 17 March 2009 в 15:25
поделиться

4 ответа

Все ответы, данные до сих пор, имеют немного ответ, но являются неполными. Вам нужен MarshalAs - ByValArray, а также новое, Ваши MSTrackDatas уже являются ссылками, таким образом, Вы не должны проходить мимо них касательно, и необходимо проверить, какое соглашение о вызовах ICEAPI представляет, если это - StdCall, Вы не должны изменять ничего, но если это будет cdecl, то необходимо будет добавить CallingConvention к атрибуту DllImport. Кроме того, Вы, возможно, должны добавить, что MarshalAs приписывает Вашему bool возвращаемому значению, чтобы удостовериться, что он упорядочен, поскольку 4-байтовые WinApi разрабатывают bool. Вот объявление, что Вам (вероятно), будет нужно:

public const int MAX_ICE_MS_TRACK_LENGTH = 256;

[StructLayout(LayoutKind.Sequential)]
public class MSTrackData {
    public UInt32 nLength;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]
    public Byte[] TrackData = new byte[MAX_ICE_MS_TRACK_LENGTH];
}

[DllImport("ICE_API.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EncodeMagstripe(IntPtr hDC,
                [In] MSTrackData pTrack1,
                [In] MSTrackData pTrack2,
                [In] MSTrackData pTrack3,
                [In] MSTrackData reserved);
5
ответ дан 16 December 2019 в 21:46
поделиться

Я определил бы Массив байтов не с новым, но использовал бы следующий код вместо этого для инициализации правильного размера:

[MarshalAs (UnmanagedType.byValTSt, SizeConst =256)] общедоступный Байт только для чтения [] TrackData;

Я использовал это успешно на массивах символов в прошлом.

2
ответ дан 16 December 2019 в 21:46
поделиться

Смотрит на меня как проблема, то, что Вы передаете ссылку ссылкой. С тех пор MSTrackData класс (т.е. ссылочный тип), передавание его ссылкой похоже на передачу от указателя к указателю.

Измените свой управляемый прототип на:

public static extern bool EncodeMagstripe(IntPtr hDC,
                    MSTrackData pTrack1,
                    MSTrackData pTrack2,
                    MSTrackData pTrack3,
                    MSTrackData reserved);

См. статью MSDN о передающих структурах.

1
ответ дан 16 December 2019 в 21:46
поделиться

У меня была почти такая же проблема, но с ReadMagstripe. И решение, представленное здесь для EncodeMagstripe, не работало для ReadMagstripe! Я думаю, причина того, что это не сработало, заключалась в том, что ReadMagstripe должен возвращать данные в структуру / класс TRACKDATA, в то время как EncodeMagstripe передает данные только в dll, а данные в TRACKDATA не нужно изменять. Вот реализация, которая в конечном итоге сработала для меня - как с EncodeMagstripe, так и с ReadMagstripe:

    public const int MAX_ICE_MS_TRACK_LENGTH = 256;
    [StructLayout(LayoutKind.Sequential)]
    public struct TRACKDATA
    {  
        public UInt32 nLength;
        [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)]
        public string szTrackData;
    }


    [DllImport("ICE_API.dll", EntryPoint="_ReadMagstripe@20", CharSet=CharSet.Auto, 
        CallingConvention=CallingConvention.Winapi, SetLastError=true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool ReadMagstripe(int hdc, ref TRACKDATA ptrack1, ref TRACKDATA ptrack2,
         ref TRACKDATA ptrack3, ref TRACKDATA reserved);

    [DllImport("ICE_API.dll", EntryPoint="_EncodeMagstripe@20", CharSet=CharSet.Auto,
        CallingConvention = CallingConvention.Winapi, SetLastError=true)]
    public static extern bool EncodeMagstripe(int hdc, [In] ref TRACKDATA ptrack1, [In] ref TRACKDATA ptrack2,
        [In] ref TRACKDATA ptrack3, [In] ref TRACKDATA reserved);


/*
        ....
*/


    private void EncodeMagstripe()
    {
        ICE_API.TRACKDATA track1Data = new ICE_API.TRACKDATA();
        ICE_API.TRACKDATA track2Data = new ICE_API.TRACKDATA();
        ICE_API.TRACKDATA track3Data = new ICE_API.TRACKDATA();
        ICE_API.TRACKDATA reserved = new ICE_API.TRACKDATA();

        //if read magstripe
        bool bRes = ICE_API.ReadMagstripe(printer.Hdc, ref track1Data, ref track2Data,
            ref track3Data, ref reserved);

        //encode magstripe
        if (bRes)
        {
            track2Data.szTrackData = "1234567890";
            track2Data.nLength = 10;

            bRes = ICE_API.EncodeMagstripe(printer.Hdc, ref track1Data, ref track2Data, ref track3Data, ref reserved);
        }
    }
0
ответ дан 16 December 2019 в 21:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: