Предложенное решение является излишне сложным. Бесчисленные переназначения переменных и цикл - рецепт головной боли. Вот упрощенная альтернатива -
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))
Все ответы, данные до сих пор, имеют немного ответ, но являются неполными. Вам нужен 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);
Я определил бы Массив байтов не с новым, но использовал бы следующий код вместо этого для инициализации правильного размера:
[MarshalAs (UnmanagedType.byValTSt, SizeConst =256)] общедоступный Байт только для чтения [] TrackData;
Я использовал это успешно на массивах символов в прошлом.
Смотрит на меня как проблема, то, что Вы передаете ссылку ссылкой. С тех пор MSTrackData
класс (т.е. ссылочный тип), передавание его ссылкой похоже на передачу от указателя к указателю.
Измените свой управляемый прототип на:
public static extern bool EncodeMagstripe(IntPtr hDC,
MSTrackData pTrack1,
MSTrackData pTrack2,
MSTrackData pTrack3,
MSTrackData reserved);
См. статью MSDN о передающих структурах.
У меня была почти такая же проблема, но с 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);
}
}