я нашел следующий отрывок при чтении источника для
Tempfile#initialize
в оперативной библиотеке Ruby:begin tmpname = File.join(tmpdir, make_tmpname(basename, n)) lock = tmpname + '.lock' n += 1 end while @@cleanlist.include?(tmpname) or File.exist?(lock) or File.exist?(tmpname)
На первый взгляд, я принял, в то время как модификатор будет оценен, прежде чем содержание начинает... конец, но дело не в этом. Наблюдайте:
>> begin ?> puts "do {} while ()" >> end while false do {} while () => nil
, Как Вы ожидали бы, цикл продолжит выполняться, в то время как модификатор верен.
>> n = 3 => 3 >> begin ?> puts n >> n -= 1 >> end while n > 0 3 2 1 => nil
, В то время как я был бы рад никогда не видеть эту идиому снова, начните..., конец довольно мощен. Следующее является общей идиомой к memoize метод остроты без параметрических усилителей:
def expensive @expensive ||= 2 + 2 end
Вот является ужасный, но быстрый путь к memoize чем-то более сложным:
def expensive @expensive ||= begin n = 99 buf = "" begin buf << "#{n} bottles of beer on the wall\n" # ... n -= 1 end while n > 0 buf << "no more bottles of beer" end end
Первоначально записанный Jeremy Voorhis . Содержание было скопировано здесь, потому что это, кажется, было удалено от инициирующего сайта. Копии могут также быть найдены в веб-Архив и в Форум Шума Ruby . - тарифицируют Ящерицу
StructureToPtr expects struct object, and foo is not structure it is array, that is why exception occurs.
I can suggest you to write structures in cycle (sadly, StructureToPtr does not have overload with Index):
long LongPtr = ptr.ToInt64(); // Must work both on x86 and x64
for (int I = 0; I < foo.Length; I++)
{
IntPtr RectPtr = new IntPtr(LongPtr);
Marshal.StructureToPtr(foo[I], RectPtr, false); // You do not need to erase struct in this case
LongPtr += Marshal.SizeOf(typeof(Rect));
}
Another option is to write structure as four integers, using Marshal.WriteInt32:
for (int I = 0; I < foo.Length; I++)
{
int Base = I * sizeof(int) * 4;
Marshal.WriteInt32(ptr, Base + 0, foo[I].Left);
Marshal.WriteInt32(ptr, Base + sizeof(int), foo[I].Top);
Marshal.WriteInt32(ptr, Base + sizeof(int) * 2, foo[I].Right);
Marshal.WriteInt32(ptr, Base + sizeof(int) * 3, foo[I].Bottom);
}
And the last, you can use unsafe keyword, and work with pointers directly.
Вы можете попробовать следующее:
RECT[] rects = new RECT[ 4 ];
IntPtr[] pointers = new IntPtr[4];
IntPtr result = Marshal.AllocHGlobal(IntPtr.Size * rects.Length);
for (int i = 0; i < rects.Length; i++)
{
pointers[i] = Marshal.AllocHGlobal (IntPtr.Size);
Marshal.StructureToPtr(rects[i], pointers[i], true);
Marshal.WriteIntPtr(result, i * IntPtr.Size, pointers[i]);
}
// the array that you need is stored in result
И не забудьте освободить все, когда закончите.
Arbiter дал вам один хороший ответ о том, как упорядочивать массивы структур. Для таких непреобразуемых структур, как эти, я лично использовал бы небезопасный код, а не вручную маршалинг каждого элемента в неуправляемую память. Примерно так:
RECT[] foo = new RECT[4];
unsafe
{
fixed (RECT* pBuffer = foo)
{
//Do work with pointer
}
}
или вы можете закрепить массив с помощью GCHandle.
К сожалению, вы говорите, что вам нужно отправить эту информацию другому процессу. Если сообщение, которое вы публикуете, не является одним из тех, для которых Windows обеспечивает автоматический маршалинг, у вас есть другая проблема. Поскольку указатель относится к локальному процессу, он ничего не значит в удаленном процессе, и отправка сообщения с этим указателем вызовет неожиданное поведение, включая вероятный сбой программы. Итак, что вам нужно сделать, это записать массив RECT в память другого процесса, а не в вашу. Для этого вам нужно использовать OpenProcess для получения дескриптора процесса, VitualAllocEx для выделения памяти в другом процессе, а затем WriteProcessMemory для записи массива в виртуальную память другого процесса.
Опять же, к сожалению, если вы переходите от 32-битного процесса к 32-битному процессу или с 64-битного процесса на 64-битный процесс, все довольно просто, но от 32-битного процесса к 64-битному процессу все может стать немного сложным. VirtualAllocEx и WriteProcessMemory на самом деле не поддерживаются от 32 до 64. Вы можете добиться успеха, если попытаетесь заставить VirtualAllocEx выделить свою память в нижних 4 ГБ 64-битного пространства памяти, чтобы полученный указатель был действителен для вызовов API 32-битного процесса, а затем записать с этим указателем. Кроме того, у вас могут быть различия в размере структуры и упаковке между двумя типами процессов.