Разработка внешних компонент на ассемблере goAsm




Принцип обмена данными из 1С с сайтом (на MySQL) и выдачи (публикации) этих данных по запросу.
PHP-Скрипт автоматической загрузки данных из файла данных в формате CSV в базу данных сайта работающего на WordPress.

В продолжение моей темы: 1С:Альфа-Авто Автосалон Автосервис: обмен с сайтом.
С помощью данного скрипта можно загружать в автоматическом режиме, по расписанию, данные сервисных книжек (ремонтов авто) из 1С:Альфа-Авто Автосалон Автосервис.
Также можно загружать данные в ручном режиме: для этого делается скрытая страница, где размещается специальная кнопка.
Комментарии размещенные внутри скрипта разъяснят логику и порядок действия.
Комментарии с "/////    echo" использовались для отладки.
Дополнительно создана таблица для журналирования результатов загрузки данных.
Скрипт включает в себя защиту от SQL инъекций (думаю безопасность соблюдена в полной мере).
В кратце:
1. Пишется скрипт, который запускает этот.
2. Создается регламентное задание в WordPress, по которому запускается скрипт из п.1. 
3. Этот скрипт осуществляет проверку на существование файла обмена в папке.
4. Если данные не новые, загрузка не производится.
5. Если данные новые, очищается таблица сервисных книжек.
6. Загружаются новые данные.

Собственно сам скрипт:

<?php // Полная загрузка сервисных книжек, создан 2024-01-05 12:44:55

global $wpdb2;
global $failure;
global $file_hist;

/////  echo '<H2><b>Старт загрузки</b></H2><br>';

$failure=FALSE;
//подключаемся к базе
$wpdb2 = include_once 'connection.php'; ; // подключаемся к MySQL
// если не удалось подключиться, и нужно оборвать PHP с сообщением об этой ошибке
if (!empty($wpdb2->error))
{
/////   echo '<H2><b>Ошибка подключения к БД, завершение.</b></H2><br>';
$failure=TRUE;
wp_die( $wpdb2->error );
}

$m_size_file=0;
$m_mtime_file=0;
$m_comment='';
/////проверка существования файлов выгрузки из 1С
////файл выгрузки сервисных книжек
$file_hist = ABSPATH.'/_1c_alfa_exchange/AA_hist.csv';
if (!file_exists($file_hist))
{
/////   echo '<H2><b>Файл обмена с сервисными книжками не существует.</b></H2><br>';
$m_comment='Файл обмена с сервисными книжками не существует';
$failure=TRUE;
}

/////инициируем таблицу лога
/////если не существует файла то возврат и ничего не делаем
if ($failure){
///включает защиту от SQL инъекций и данные можно передавать как есть, например: $_GET['foo']
/////   echo '<H2><b>Попытка вставить запись в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>$m_comment));
wp_die();
/////    echo '<H2><b>Возврат в начало.</b></H2><br>';
return $failure;
}
/////проверка лога загрузки, что бы не загружать тоже самое
$masiv_data_file=stat($file_hist);   ////передаем в массив свойство файла
$m_size_file=$masiv_data_file[7];    ////получаем размер файла
$m_mtime_file=$masiv_data_file[9];   ////получаем дату модификации файла
////создаем запрос на получение последней удачной загрузки
////выбираем по штампу времени создания (редактирования) файла загрузки AA_hist.csv, $m_mtime_file

/////   echo '<H2><b>Размер файла: '.$m_size_file.'</b></H2><br>';
/////   echo '<H2><b>Штамп времени файла: '.$m_mtime_file.'</b></H2><br>';
/////   echo '<H2><b>Формирование запроса на выборку из лога</b></H2><br>';
////препарируем запрос
$text_zaprosa=$wpdb2->prepare("SELECT * FROM `vin_logs` WHERE `last_mtime_upload` = %s", $m_mtime_file);
$results=$wpdb2->get_results($text_zaprosa);

if ($results)
{   foreach ( $results as $r)
{
////если штамп времени и размер файла совпадают, возврат
if (($r->last_mtime_upload==$m_mtime_file) && ($r->last_size_upload==$m_size_file))
{////echo '<H2><b>Возврат в начало, т.к. найдена запись в логе.</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>$m_mtime_file,'last_size_upload'=>$m_size_file,'comment'=>'Загрузка отменена, новых данных нет, т.к. найдена запись в логе.'));
wp_die();
return $failure;
}
}
}
////если данные новые, пишем в лог запись о начале загрузки
/////echo '<H2><b>Попытка вставить запись о начале загрузки в лог таблицу</b></H2><br>';
$insert_fail_zapros=$wpdb2->insert('vin_logs', array('time_stamp'=>time(),'last_mtime_upload'=>0, 'last_size_upload'=>$m_size_file, 'comment'=>'Начало загрузки'));

////очищаем таблицу
$clear_tbl_zap=$wpdb2->prepare("TRUNCATE TABLE %s", 'vin_history');
$clear_tbl_zap_repl=str_replace("'","`",$clear_tbl_zap);
$results=$wpdb2->query($clear_tbl_zap_repl);
/////   echo '<H2><b>Очистка таблицы сервисных книжек</b></H2><br>';
if (empty($results))
{
/////   echo '<H2><b>Ошибка очистки таблицы книжек, завершение.</b></H2><br>';
//// если очистка не удалась, возврат
$failure=TRUE;
wp_die();
return $failure;
}

////загружаем данные
$table='vin_history';         // Имя таблицы для импорта
//$file_hist Имя CSV файла, откуда берется информация     // (путь от корня web-сервера)
$delim=';';          // Разделитель полей в CSV файле
$enclosed='"';      // Кавычки для содержимого полей
$escaped='\

40 Comments

  1. drmaxart

    Большое спасибо за труд, очень интересно на ВК посмотреть изнутри на таком уровне

    Reply
  2. PerlAmutor

    Не люблю COM из-за необходимости регистрировать компоненту в системе и поддержку только Windows.

    Пытался как-то собрать примеры NativeAPI от 1С через MinGW, так как не перевариваю Microsoft с их компилятором С++, исходники под который не переносятся без танцев с бубнами в другие ОС из-за тесной привязки к собственным, виндовым, типам. А также из-за разности интерпретации стандартов С++ с gcc. Исходники то я собрал в .dll, но вот подключить не смог из разности интерфейсов получившихся в .dll от gcc и msvc В общем из программ собранных с помощью msvc нельзя вызывать .dllки собранные gcc. Кроме того вместе с .dll компоненты нельзя «тащить» с собой зависимые .dllки, типа iconv.dll. 1С предполагает наличие только одного файла NativAPI. Если в zip архив рядом положить все зависимые .dll, 1С их просто проигнорирует. Зависимые dll невозможно описать в XML файле.

    В общем технология мне не понравилась своей ограниченностью.

    Reply
  3. Идальго

    Так-то круто конечно))

    Reply
  4. ifal

    Редкая с технической стороны статья на инфостарте, пишите о NativeApi обязательно.

    Reply
  5. chessman

    (1) Спасибо. Всё ли понятно?

    Reply
  6. chessman

    (4) Спасибо. Все ли понятно? Может что-то нужно добавить/убрать?

    Reply
  7. ifal

    (6) Более чем, все по делу.

    Reply
  8. Zab

    Класс. Начало статьи обещает «вкусное» чтение. В закладки, чтобы прочитать неторопливо и внимательно позже.

    Reply
  9. DoctorRoza

    Думаю, суть этой статьи поняло не больше 1% аудитории, к коим, увы, я не отношусь!

    Reply
  10. nomadon

    (2) а по абсолютному пути dll можно прицепить ?

    Reply
  11. aspirator23

    (9) Во всяком случае это интереснее чем челябинские сериалы. 🙂

    Reply
  12. Darklight

    Внешние компоненты по технологии COM на ассемблере? Вызовите кто-нибудь медиков автору — крышу явно снесло! Но коли автор хочет разъяснить создание на ассембрере не только COM но и Native компонент — то ладно, не забирайте автора в Кащенку — ему ещё про Native писать.

    В общем, сугубо для расширения кругозора — статья очень даже хорошая — и некоторым специалистам вполне полезная! А выше — это я, просто, немного постебался от шока — пойду приму успокоительное…

    Автор — пиши есЧО!

    Reply
  13. frkbvfnjh

    Да, пишите еще!!! Сделайте еще шаблон-заготовку для NativeAPI.

    Reply
  14. chessman

    (12)

    (13)

    Боюсь, что тогда из Кащенко точно не выпустят.

    На самом деле шаблон уже есть. Его только немного поправить нужно, с учетом ошибок которые я нашел в процессе подготовки этой части. В следующей части выложу.

    Reply
  15. frkbvfnjh

    (14) Ваще супер! Вам будут поклоняться как языческому божеству и приносить девственниц в жертву 🙂

    Reply
  16. starik-2005

    Статья в принципе классная, но огорчили две вещи:

    1. Как уже сказали, COM — это ограничение по платформе, при этом давно уже есть NativeAPI. Было бы куда интереснее рассмотреть именно его.

    2. Зачем делать dec ecx; jnz @loop? Почему не используете LOOP @loop? Но это, конечно, придирка чистой воды.

    Ну и есть еще одно некоторым образом возражение — зачем АСМ? Скорости он по сравнению с С/С++ не даст, если программист не особо владеет глубокими знаниями процессорной архитектуры. Да и код на АСМе будет большой и практически неподдерживаемый, ибо АСМ знают на столько небольшое количество людей, что на Инфостарте их, МИХО, можно пересчитать по пальцам одной руки.

    Reply
  17. starik-2005

    (15)

    Вам будут поклоняться как языческому божеству и приносить девственниц в жертву

    Тащи две.

    Reply
  18. spectre1978

    Крутяк! Не ожидал ничего подобного увидеть на ИС. Плюс однозначно.

    Reply
  19. PerlAmutor

    Мне покоя не дает другая задумка — генерить исходники компоненты с помощью 1С, компилировать на сервере в NativeAPI с помощью другой компоненты/утилиты (компилера) и вызывать все что душе угодно на стороне сервера, на что хватит прав.

    Reply
  20. PerlAmutor

    (10) Честно не помню. Там вроде бы есть особенность, когда 1С копирует твою компоненту куда-то к себе в кэш в одну из пользовательских папок, естественно делает она это без учета её зависимости от других .dll’ок.

    Reply
  21. chessman

    (16)

    1. NativeAPI планируется в следующей части. Жаль только, что в компоненту ничего кроме примитивных типов передать нельзя.

    2. Тут ошибся. Интересно, что в других местах именно loop используется.

    Почему именно asm…мне кажется, что так можно лучше прочувствовать «технологии», поскольку используются примитивные конструкции, которые легче воспринимать. Согласен, что код занимает несколько больше места, зато результат того стоит. Опять же, я не призываю поголовно использовать asm, а просто предлагаю его как альтернативу.

    Reply
  22. CheBurator

    Девственниц у меня под рукой (а где же еще?) нет, поэтому молюсь как умею:

    BE! BNE!

    BR 14!

    0C1! 0C4!

    //GO SYSIN DD!

    DVOL PTOM01!

    Reply
  23. IgorKissil

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

    Считаю, гораздо перспективней создать паттерн, чтобы разработчик при написании ВК был сконцентрирован на своих задачах, используя готовую библиотеку, вроде https://infostart.ru/public/332786/ (не сочтите за рекламу). Но в упомянутой статье рассматривается пример для .net и com-компонент. Для нативных компонент можно использовать одну из библиотек C++ для reflection, а ассемблеру оставить его специфические задачи.

    Reply
  24. KAV2

    (21) Есть варианты для передачи сложных значений по Native API. Например, последовательный вызов функций для передачи коллекций или JSONXML.

    Reply
  25. Prometeus2011

    Мужик, Респект тебе! Снова вспомнился 98й. Дивный вкус, цвет и запах свободы (не только написания кода). Все пронеслось в голове: юность, SoftIce, почивший в бозе http://www.wasm.ru, вычисление базы кода через стек, защита от отладки через TLS — обработчики, полиморфное шифрование… Эх… где мои 17 лет.

    Reply
  26. chessman

    (23) Игорь, спасибо за комментарий. Цель данного материала была, во-первых, — развеять миф, который, как мне кажется, сложился в среде разработчиков на платформе 1С, что ассемблер это сложно. Во-вторых, убрать все «обёртки» в виде сред разработки и показать, что можно обойтись более простыми инструментами. В-третьих, подать материал, используя примитивные конструкции. Не уверен, что у меня получилось идеально, но думаю, что какой-то туман я рассеял.

    То, что касается производительности труда, то я давно (со времён 1С++) использую на практике Com-объект DynamicWrapperX, который позволяет (по крайней мере мне) решать некоторый класс задач, не прибегая к созданию очередной внешней компоненты.

    Reply
  27. chessman

    (24) Можно поподробнее?

    Reply
  28. KAV2

    (27) Ну например, вам надо передать в компоненту коллекцию значений, скажем список значений. Вы из компоненты вызываете функцию, инициализирующую начало передачи списка, скажем Begin(), далее вызываете функцию, передающую одно значение коллекции за один раз, до тех пор, пока вся коллекция не будет передана и по завершении, вызываете функцию End(), для обозначения завершения коллекции.

    С JSON можно сериализовать список значений и передать его строкой, а компонента десериализует.

    Тоже самое можно делать и в обратную сторону.

    Reply
  29. chessman

    (28) С сериализацией понятно.

    А как сделать «передающую одно значение коллекции за один раз», если значение имеет не примитивный тип?

    Reply
  30. Darklight

    (16) Думаю что данная статья больше годится не для практического написания ВК на чистом ассемблере, а для того, чтобы показать как оно устроено изнутри, для тех случаев, когда кому-то понадобится покопаться, скажем, в уже скомпилированном коде — который, при декомпилировании (и отладке без символьного debug файла), будет представлять поток ассемблерных инструкций. Зачем? Это уже другой вопрос. но, к примеру, вот писал я ВК — а она не подлкючается в 1С — возвращает — ложь при подключении и всё — без каких либо ошибок — хоть ты тресни! Вот и берёшь отладчик — и смотришь, что там по инструкциям не так — а без него — это копаться в исходном коде — и вникать в тонкости соответствия стандартам языка и подключенных библиотек и их ограничений для той или иной платформы. В прочем с отладчиком тоже мороки было бы много. Но что делать когда нет исходных кодов? Есть разные готовые старые компоненты — и они — так же не подключаются к 1С 8.3 сейчас — а если очень надо заставить их заработать — тогда только дизассемблирование и анализ…. Поэтому важно понимать и как COM и как Native компоненты устроены в инструкциях ассемблера! Конечно, это статья не для всех, а только для узкого круга программистов с «особенной» психикой! Обычно это те деды, которые, ранее уже изучали и даже, хоть немного, программировали на ассемблере!

    Reply
  31. KAV2

    (29) Используя ту же идею что и для первого уровня, технически это возможно, целесообразно ли, другой вопрос.

    Reply
  32. chessman

    (31) Ну, т.е. только через строку.

    Reply
  33. starik-2005

    (26)

    развеять миф, который, как мне кажется, сложился в среде разработчиков на платформе 1С, что ассемблер это сложно

    Миф развеян? Думаю, что нет )))

    Reply
  34. KAV2

    (32) Нет не только.

    Reply
  35. Rego1337h

    (25) + обратные ксорки 😉 http://zxpress.ru/article.php?id=6266

    Reply
  36. PerlAmutor

    (25) Аналогично. От SoftIce до сих пор существуют положительные впечатления из области мощнее и интереснее отладчика в своей жизни я больше нигде не видел. На wasm тоже был зарегистрирован, создавал темы. Пробовал Tasm, Masm, Nasm в итоге остановился на Fasm. Писал резидентные утилиты под MS DOS. А чего только IDA Pro стоит. Особое удовольствие получал используя порты устройств,

    для CDROM, FM тюнера, клавиатуры (мигание лампочками), PC Speaker (голос Ленина из PC спикера в компьютерном классе при отсутствии колонок — развлечение для всего класса). До сих пор на полках пылятся книжечки.

    Reply
  37. agafonov_andrei

    (25) Прямо мысли мои прочитал

    Reply
  38. agafonov_andrei

    Спасибо Вам большое за статью! Как раз сейчас есть острая необходимость написать компоненту, но проблема в том, что последнее из чего я писал (не 1С и не T-SQL) под windows был FASM и это было лет 10 назад. Есть огромное желание написать компоненту не на C, а именно на asm’е. По этому с нетерпением жду про NativeAPI.

    Reply
  39. chessman

    (38) Интересно, а что за задачу будете решать?

    Reply
  40. strek_ivan

    Продвинутая статья для продвинутых программистов! Автору низкий поклон.

    Отличную производительность можно получить используя параллельные вычисления на видеокартах (технология CUDA от nVidia). Для манипуляций данным вычислительным сервером требуется интеграция с клиентом 1С. Почему бы для этих целей не воспользоваться старым добрым COM’ом?!

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *