Помощь · Поиск · Пользователи · Календарь
Полная версия этой страницы: Продвинутая работа с dll в mdm Zinc
Flash Zone Forum > Macromedia Flash > Софт
chingachgoog
Zinc позволяет чудесно использовать dll-ки 1
Причем спокойно можно использовать стандартные виндовые библиотеки, т.е. winAPI. Таким образом приложения на Цинке становяться практически неотличимыми по функционалу от приложений написанных на низкоуровневых языках типа Си и Дельфи. И ничто бы не портило этой радужной картины, кабы не ограничения работы Цинка с dll-ками.

Цинк передает и принимает параметры из функций dll в виде простых значений (по сути строк). Это сильно ограничивает возможности работы с dll, т.к. многие функции winAPI, например, принимают и возвращают сложные данные (например, структуры). Единственным известным мне решением до недавнего времени оставалось использовать dll-прокладок (медиаторов) между Цинком и "сложными" dll-ками. Писались эти прокладки на Дельфи, либо Сях, что делало их доступность для ActionScript-программистов весьма сомнительной. К тому же надо было подготавливать специальный интерфейс для общения с медиатором. Вообщем дело крайне утомительное.

И вот тут что-то упало на голову (яблоко? smile.gif ). Портируя очередную функцию с си, я вдруг заметил то, что давно было перед глазами. Это постоянно используется в сях - передача не значения, а адреса памяти (ссылки) где хранится значение (любой сложности!). Принцип решения был найден - осталось "всего лишь" воплотить его в жизнь smile.gif И тут бы я и остался бы с розовыми мечтами, если бы не наводка моего товарища  tortMaker-а и огромнейшая помощь от alexcon314, который в общем-то и решил эту задачу.

Собственно решение.

Используется стандартная библиотека msvcrt.dll и три функции в ней:
malloc - резервируем необходимое число байтов (памяти) и получаем адрес первого из них.
memset - записываем значение(я) с выбранного адреса памяти
memcpy - возращает значение из указанного адреса памяти (возвращается строка чаров, но только до первого нулевого символа и порой в "перевернутом виде")

Код
msvcrt = new mdm.DLL(mdm.System.Paths.windows+"/system32/msvcrt.dll");
////////////////////////////////////////////
//       Определяем имя пользователя      //
////////////////////////////////////////////

function getUserName(){
    msvcrt.clear()        
    msvcrt.addParameter("integer", 0xff);
    var memU = msvcrt.call("integer", "malloc");
    
    msvcrt.clear();         
    msvcrt.addParameter("integer", 4);
    var memN = msvcrt.call("integer", "malloc");
    
    msvcrt.clear();
    msvcrt.addParameter("integer", memN);
    msvcrt.addParameter("integer", 0xff);
    msvcrt.addParameter("integer", 1);
    msvcrt.call("integer", "memset");
    
    advapi32.clear(); // BOOL WINAPI GetUserName( __out    LPTSTR lpBuffer, __inout  LPDWORD lpnSize);
    advapi32.addParameter("integer", memU);
    advapi32.addParameter("integer", memN);
    var b = advapi32.call("boolean","GetUserNameA");

    advapi32.clear();
    
    msvcrt.clear(); // void *memcpy( void *dest, const void *src,  size_t count );
                                    // dest - New buffer.
                                    // src - Buffer to copy from.
                                    // count - Number of bytes to copy.
                                    // Return Value - The value of dest.
    msvcrt.addParameter("integer", memU); // адрес нового буфера
    msvcrt.addParameter("integer", memU); // адрес буфера из которого копируем (сам себя)
    msvcrt.addParameter("integer", 0xff); // число байтов которые копируем
    var u = msvcrt.call("string", "memcpy"); // возвращаемое значение из нового буфера

    msvcrt.clear();
    msvcrt.addParameter("integer", memU);
    msvcrt.call("integer", "free");

    msvcrt.clear();
    msvcrt.addParameter("integer", memN);
    msvcrt.call("integer", "free");
    
    msvcrt.clear();
    
    return u
}


Вообщем работаем с winAPI практически без ограничений!

1 Цинк работает с классом DLL с рядом ограничений:
- ограничение по платформе. Это либо Винда, либо Линукс (но Цинк проект должен быть тогда версии 3, скомпилирован под Винду(!) и запущен на Линуксе через WINE)
- ограничение по типу dll. Библиотеки могут быть только win32-типа, com и .NET не выполняются.
tiHo
 интересно, спасибо за информацию.
MustLive
Цитата
Zinc позволяет чудесно использовать dll-ки

Работа из флеша с dll и WinAPI (через Zinc в данном случае) - это весьма интересно. И при использовании флеша для создания десктопных приложений может весьма пригодиться. Когда нужно использовать не только возможности самого флеша (т.е. просто сделать exe-проект из флешки), а когда нужно сделать полноценное приложение (например работающее с WinAPI).

Молодец chingachgoog, который с товарищами tortMake и alexcon314 разработали данный алгоритм работы, который позволяет обходить ограничения Zinc (в частности на передачу параметров функций). Данная информация без сомнения пригодиться людям wink.gif.

Цитата
низкоуровневых языках типа Си и Дельфи

Когда это Си и Дельфи стали низкоуровневыми smile.gif. Это высокоуровневые языки - согласно официальному разделению на языки низкого, высокого и сверхвысокого уровня. А учитывая большие низкоуровневые возможности в Си, его иногда ещё называют языком среднего уровня. Низкий уровень - это уже ассемблер. Ниже только байт коды и машинные коды.
Chaos
 респект!)
Varcharamir
Скажите пожалуйста, как после этого использовать полученную ссылку. Я представляю, что ссылка отправляется в виде параметра (строки) в Зинк, но как из флэша-зинка работать с сылкой? Там, видимо, есть какая-то простая функция о которой я не знаю. И хотелось бы уточнить, есть ли альтернативные решения для Zinc 4.0. mdm во всю хвалились его способностью работать со всеми возможными параметрами, но я пока не могу понять на сколько это правда. Т.е. вопрос в том, отпала ли необходимость в таких ухищрениях с новым Зинком?
chingachgoog
Как использовать ссылку полностью объяснено в примере. )))

Что касается 4-го Цинка,  то судя по лайвдокам класс работы с dll остался без изменений. Так что все актуально по-прежнему.
Varcharamir
Спасибо. Честно говоря я не ожидал, что мне ответят. Чаще всего люди пишут статью и забывают...

У меня еще есть несколько вопросов. Мне необходимо передать ссылку на функцию, как параметр. В C++ она бы вызывалась, как function1(&function2). Обе функции void (т.е. ничего не возвращают). Как я понимаю, мне надо передать указатель на начало функции function2. Что-то вроде mydll.addParameter("integer", function2); , а затем кинуть ее в функцию mydll.call("none", "function1");. Но я почти уверен, что так просто не выйдет.

И второй вопрос можно ли как-то достать глобальную переменную из dll-ки все так же не меняя библиотеку и не подгружая ее в Zinc? Т.е можно ли это сделать без создания дополнительной функции, которая бы возвращала эту переменную, как ответ на запрос?
chingachgoog
Не, работает не так. Просто попробуйте воспроизвести этот пример.

Без этих функций не обойтись:

malloc - после call("integer", "malloc") получаем адрес первого из зарезервированных байтов.
memset - call("integer", "memset") записываем значение(я) с выбранного адреса памяти. Не помню, почему там возращаемое значение integer, а не none. Может и none проатит )))
вызов основной функции с параметрами... Только тут моет быть любая функция, которая нам нужна ...
memcpy - call("string", "memcpy") возращает значение (строка) из указанного адреса памяти (того, что мы получили в call("integer", "malloc"))

Цитата(Varcharamir @ 16.02.2012 - 09:44) *
И второй вопрос можно ли как-то достать глобальную переменную из dll-ки все так же не меняя библиотеку и не подгружая ее в Zinc? Т.е можно ли это сделать без создания дополнительной функции, которая бы возвращала эту переменную, как ответ на запрос?


Весь вопрос КУДА ее нужно достать? Если во флеш/Цинк, то как они ее прочтут/достанут, если вообще об этой переменной не знают? Только если в самой dll будет механизм доставки ее во флеш/Цинк - например, через LocalConnection.
Русская версия IP.Board © 2001-2014 IPS, Inc.