Пишем свою оболочку для FP под Windows. Шаг 6.
Бинарный буфер для обмена данными.
На этот раз я расскажу об одном трюке (трике?).
ExternalInterface, как вы знаете, работает только со строками: в XML пакуются числа, булы, что там еще.. А что если надо обмениваться бинарными данными? Да, конечно, есть basе64. Но все же.
Так вот. Есть несложный ход, который позволяет организовать бинарный буфер
для обмена данными. Об этом я немного рассказал здесь: http://www.flasher.ru/forum/blog.php?b=265
Итак, идея заключается в том, чтобы на стороне флеша создать экземпляр ByteArray, задать ему подходящий размер, ну, к примеру 1024*1024 (1Mб). Это и будет буфер. Размер его можно потом менять динамически, но это уже детали. Важно, чтобы экземпляр никуда не делся после создания, ссылку на него надо получше защитить.
Теперь надо получить указатель на этот буфер на стороне оболочки. Флеш не умеет передавать, да что там передавать, определять адреса своих переменных. Тут он нам ничем не поможет. К счастью, в С++ мы ничем таким не свзаны.
Займемся практикой.
package gui { import flash.events.MouseEvent; import flash.external.ExternalInterface; import flash.utils.ByteArray; public class BinaryBuffer extends Sprite { private var sharedMemBlock:ByteArray = new ByteArray(); public function GuiTest5() { super(); sharedMemBlock.length = 1024 * 1024; eggs(sharedMemBlock); var res:String = ExternalInterface.call("bla");// ok // проверьте содержимое sharedMemBlock // (acegikmoacegikmo HELLO, BUFFER!) } private static function eggs(arr:ByteArray):void { for (var i:uint = 0; i < 8; i++) { arr[i] = arr[i+8] = 0x61 + i + i; } } } }
пишется «строка» «acegikmoacegikmo». Это закладка, «яйца».
Дальше дергаем EI. Ну, в данном примере название вызываемой функции не имеет значения. Важно просто поймать этот вызов в оболочке.
Поймав вызов, мы отправляемся на охоту (eggshunting):
HRESULT MyFlash::FlashCall (_bstr_t xml_request) { LPBYTE sharedMemBlock = FindSharedMemBlock(); lstrcpyA((CHAR*)&sharedMemBlock[16]," HELLO, BUFFER!"); // само-собой, в бинарный буфер можно писать не только строку :) SetReturnValue(_bstr_t("<string>ok</string>")); return S_OK; } LPBYTE MyFlash::FindSharedMemBlock() { UINT memBlockSize = 1024*1024; HANDLE hProc = GetCurrentProcess(); SYSTEM_INFO si; GetSystemInfo(&si); LPBYTE lpBytes = NULL; MEMORY_BASIC_INFORMATION mi; BYTE buf[16] = {0x0}; VirtualQueryEx(hProc,si.lpMinimumApplicationAddress, &mi,sizeof(mi)); for( LPBYTE lpAddress = (LPBYTE)si.lpMinimumApplicationAddress; lpAddress < si.lpMaximumApplicationAddress; lpAddress += mi.RegionSize) { if(VirtualQueryEx(hProc, (LPCVOID)lpAddress, &mi,sizeof(mi))) { if((mi.Protect & PAGE_READWRITE) || (mi.Protect & PAGE_WRITECOPY)) { for( LPBYTE b = lpAddress; b < lpAddress + mi.RegionSize; b += 16) { if(ReadProcessMemory(hProc,(LPCVOID)b,&buf,16,NULL)) { int i = 0; while( i < 8) { if( buf[i] != 0x61 + i + i || buf[i+8] != 0x61 + i + i) break; i++; } if (i == 8) { lpBytes = b; VirtualProtect(lpAddress,memBlockSize,PAGE_EXECUTE_READWRITE,NULL); break; } } } } } } CloseHandle(hProc); return lpBytes; }
Можно попробовать соптимизировать поиск закладки, например начинать не с нижнего адреса, а... с какого? Ну, например с адреса кучи процесса, как вариант, или с верхних адресов. Если хотите — займитесь на досуге. Но на мой взгляд это не принципиально.
А теперь немного фантазии.
Раз мы имеем бинарный буфер, можем туда писать, что угодно .... то... то ... эмм... да туда ж можно залить картинку из ресурсов, к примеру, или даже «исполняемый» swf!! И это безо всяких base64 и прочей лабуды! Чувствуете драйв?
ЗЫ: Подобные эксперименты я проводил и с AS2. Там в качестве буфера высупала BitmapData. Получалось найти буфер из оболочки по тому же принципу. Но дальше я не пошел. На сторне флеша с таким "буферм" работать не очень удобно, да и в оболочке тоже не фан. Впрочем, это чисто технические трудности. Другое дело, что AS2, видимо, вообще теряет актуальность. Для "оболочкописателей", по крайней мере. Хотя, и это не факт...
Всего комментариев 6
Комментарии
01.06.2011 19:45 | |
А кстати, про это http://code.google.com/p/redtamarin/ знаешь? Я вот скоро буду разбираться, выглядит интересно на первый взгляд.
EDIT: Ой, и, кстати, а что если этот ByteArray, который ты использовал для примера, использовать для fastmemory? Туда у флеша будет гораздо более быстрый доступ на чтение / запись. |
|
Обновил(-а) wvxvw 01.06.2011 в 19:58
|
02.06.2011 13:04 | |
Интересный проект это redtamari, надо бы последить за развитием.
|
Последние записи от alexcon314
- Пишем свою оболочку для FP под Windows. Шаг 6. (19.05.2011)
- Пишем свою оболочку для FP под Windows. Шаг 5. (18.05.2011)
- Пишем свою оболочку для FP под Windows. Шаг 4. (18.05.2011)
- Пишем свою оболочку для FP под Windows. Шаг 3. (18.05.2011)
- Пишем свою оболочку для FP под Windows. Шаг 2. (17.05.2011)