gifts2017

ВК NativeAPI на Delphi и FreePascal

Опубликовал Александр Соломатин (v77) в раздел Программирование - Внешние компоненты

1CNativeLib - бесплатная библиотека Delphi для создания внешних компонент (ВК) 1С по технологии Native API.
Новая версия.
16.12.2015 Исправлена ошибка: поиск свойств и методов ВК выполнялся с учетом регистра букв.
06.10.2015 Исправлена ошибка: сообщение "некорректная работа компоненты с памятью"

 

1CNativeLib - библиотека Delphi для создания внешних компонент (ВК) 1С по технологии Native API. Библиотека легка в использовании и позволяет заниматься непосредственно функционалом ВК, не отвлекаясь на соблюдение инструкций, предоставленных фирмой 1С.

 

Для того, чтобы создать ВК с помощью 1CNativeLib, достаточно создать проект DLL, написать класс с реализацией функционала вашей ВК и зарегистрировать этот класс при загрузке dll. Минимальный проект DLL с реализацией класса с одним методом выглядит так:

 

//-----------------------------------------------------------------

 

library MiniVK;

 

uses

SysUtils, v8napi;

 

type

TMyClass = class(TV8UserObject)

function Hello(RetValue: PV8Variant; Params: PV8ParamArray;

const ParamCount: integer): boolean;

end;

 

{ TMyClass }

 

function TMyClass.Hello(RetValue: PV8Variant; Params: PV8ParamArray;

const ParamCount: integer): boolean;

begin

V8SetWString(RetValue,'Привет из Delphi!'); //устанавливаем результат функции

result := True; //Устанавливаем флаг, что функция завершилась успешно

end;

 

begin

with ClassRegList.RegisterClass(TMyClass, 'MySuperExtention', 'TMyClass') do

begin

AddFunc('Hello', 'Привет', @TMyClass.Hello, 0); //регистрируем функцию

end;

end.

 

//-----------------------------------------------------------------

 

Всё необходимое содержится в одном модуле v8napi.pas. В прилагаемом архиве сам модуль, пример, более подробное описание и шаблон для нового проекта.

 

Скачать файлы

Наименование Файл Версия Размер
1CNativeLib.zip 239
.zip 44,87Kb
17.10.12
239
.zip 44,87Kb Скачать
Вариант для FreePascal (Lazarus) 90
.zip 10,42Kb
16.10.12
90
.zip 10,42Kb Скачать
v8napi.pas от 16.12.2015 46
.pas 39,71Kb
16.12.15
46
.pas 39,71Kb Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Ярослав Тарарака (slaviksoft) 17.02.11 16:11
2. Ярослав Тарарака (slaviksoft) 18.02.11 09:55
меня интересует - этот модуль на delphi Вы сами писали или это от 1С?
3. Александр Соломатин (v77) 18.02.11 11:11
Сами конечно. Какой смысл выкладывать модуль от 1с?
4. Сергей (sipoju) 18.02.11 15:22
Извините что не в тему, но мне тяжеловато работать с Делфями :cry:
Есть ли такое же только на С++? (Borland Builder или Visual C++)
5. Александр Соломатин (v77) 18.02.11 15:33
На ИТС есть документация и примеры на Си++
6. Андрей Акулов (DrAku1a) 21.02.11 04:20
Возможно ли использование на FPC+Lazarus?
И еще - было бы неплохо и для v77 аналогичный ВК-класс сделать.
7. Александр Соломатин (v77) 21.02.11 08:22
DrAku1a пишет:

Возможно ли использование ?
И еще - было бы неплохо и для v77 аналогичный ВК-класс сделать.

Для FPC+Lazarus надо допиливать. Сходу не заработало, но заработает.
Для v77 можно сделать, но вроде как уже и так хватает.
8. Юрий Ульянов (i-man) 15.05.11 21:31
есть возможность как то передавать не простые данные в ВК, а ссылки на элементы справочников или документов и уже внутри ВК с этими элементами работать?
если можно примерчик небольшой

спасибо заранее
9. Александр Соломатин (v77) 17.05.11 11:44
Нету такой возмоности. В NativeAPI такое не предусмотрено.
10. Ийон Тихий (cool.vlad4) 17.05.11 11:50
(8) зачем? для этого 1С есть...
11. romix (romix) 01.08.11 11:14
Проверил однако работает! Спасибо!
12. romix (romix) 01.08.11 18:15
Компонента на основе этой с полезным функционалом, которого отчасти не хватало в 1С 8.2 http://infostart.ru/public/88060/ (запуск процесса, переключение раскладки и др.).
13. UncleVader (UncleVader) 01.08.11 19:33
(9) Я так понимаю что не предусмотрен возврат и ссылок на таблицу значений или на какую другую коллекцию значений?
14. johnrex 16.09.11 07:18
Скажите, пожалуйста, возможно ли с использованием NativeApi организовать поток (Delphi), который будет независимо выполнять определенные действия, и генерить в нужных ситуациях внешнее событие в 1С 8. В моем случае нужно опрашивать весы подключенные к com порту с периодичностью хотя бы раз в секунду и если они подключены при изменении веса отсылать данные в 1С. Обработчик ожидания не устраивает, так как 1С работает однопоточно и очень сильно висит при опросе com порта.
15. Сергей Мурзинов (Sergey_Murzinov) 04.10.11 22:58
Спасиюо, толковая работа
16. zag2art (zag2art) 21.10.11 19:51
17. zag2art (zag2art) 23.10.11 19:19
(9) тот же вопрос, что и в (13) ответьте пожалуйста.
18. Александр Соломатин (v77) 23.10.11 22:33
19. Александр Соломатин (v77) 23.10.11 22:35
(13) Можно передавать только простые типы данных и вернуть из ВК двоичные данные. Вроде всё пока. Остальное 1С блокирует.
20. Рамиль (mur611) 25.10.11 14:05
Здравствуйте,
Пробовал по примеру писать NativeAPI компоненту, но почему то не воспринимает функции, пишет "Поле объекта не обнаружено (Hello)". Или v8napi.pas от http://infostart.ru/public/88060/ не подходит для самого простого примера. А вообще стоит задача написать внешнюю компоненту для общения с COM портом. и используя ваш пример можно написать данную ВК?
21. Рамиль (mur611) 25.10.11 14:09
есть конечно примеры на CPP, но времени разбирать с Visual большого нет.
22. Александр Соломатин (v77) 26.10.11 12:01
(20) видимо где то чего то неправильно понаписал. У всех работает нормально, жалоб не было.
23. Рамиль (mur611) 03.11.11 12:52
есть вопрос. Заключается он в том, что в ВК на технологии СОМ обработка ошибок во ВК производилась функцией RaiseLastOSError и все работает ОК, а вот теперь вроде сделал на Native API, и при вызове данной функции ВК, 1Ска закрывается (вылетает). какие методы есть решения? не подскажете.
24. Александр Соломатин (v77) 03.11.11 13:32
(23) mur611,
V8.AddError(wcode: word; const source: PWideChar;
const descr: PWideChar;
scode: integer): boolean;

см. документацию от 1С
25. igor (igor_kav) 26.03.12 10:47
есть вопрос, как вернуть массив? входные параметры функции - число, строка, а вот вернуть функция должна массив или olevariant, каа быть?
26. Spi1y (Spi1y) 26.03.12 11:19
(25) igor_kav, только генерировать строку с внутренним представлением любой коллекции (массив, структура, список значений, и т.д.), а в 1С уже преобразуешь с помощью ЗначениеИзСтрокиВнутр(). К сожалению, я не смог найти ни одного внятного описания структуры внутреннего представления ТаблицыЗначений, а по всем остальным коллекциям формат довольно простой.
Сам на основе данного шаблона делал компоненту для внутреннего использования, с возвратом из функции массива. Если нужно, напиши, кину пример кода.
27. Spi1y (Spi1y) 26.03.12 11:26
Вот как раз и пример со структурой, у массива формат еще проще:

  pwi.cbSize := SizeOf(pwi);
  if WindowHandle <> 0 then begin
    Result := GetWindowInfo(WindowHandle, pwi);
    if Result then begin
      ResultString := '{"#",4238019d-7e49-4fc9-91db-b6b951d5cf8e,{4,{{"S","Лево"},{"N",';
      ResultString := ResultString + IntToStr(pwi.rcWindow.Left) + '}},{{"S","Верх"},{"N",';
      ResultString := ResultString + IntToStr(pwi.rcWindow.Top) + '}},{{"S","Ширина"},{"N",';
      ResultString := ResultString + IntToStr(pwi.rcWindow.Right - pwi.rcWindow.Left) + '}},{{"S","Высота"},{"N",';
      ResultString := ResultString + IntToStr(pwi.rcWindow.Bottom - pwi.rcWindow.Top) + '}}}}';
    end else
      ResultString := '{"#",4238019d-7e49-4fc9-91db-b6b951d5cf8e,{0}}';
    end;
    V8SetWString(RetValue, ResultString);
...Показать Скрыть
28. igor (igor_kav) 26.03.12 11:28
было бы здорово готовый код глянуть. скиньте, пожалуйста, на мыло igor_kav@mail.ru
спасибо!
29. igor (igor_kav) 26.03.12 11:29
спасибо! пока писал коммент, Вы уже выложили.
30. igor (igor_kav) 26.03.12 11:36
а как быть с многомерным массивом?
31. Spi1y (Spi1y) 26.03.12 12:10
Кхм, понятия не имею. Честно говоря, ни разу за всю практику не сталкивался с необходимостью использования многомерных массивов. Но, если размышлять логически, то сам формат представления для массива таков:

{"#",4238019d-7e49-4fc9-91db-b6b951d5cf8e,{КоличествоЭлементов,{ОписаниеКлюча1, ОписаниеЗначения1}, ... , {ОписаниеКлючаN, ОписаниеЗначенияN}}}

где ОписаниеКлючаN и ОписаниеЗначенияN:
{ОписаниеТипа,Значение}


Логично предположить, что если описание тпа подставить Массив, и а в значение - внутреннюю строку вложенного массива, то должно получиться то, что нужно.

Но надо проверять, конечно. Попозже гляну.
32. Spi1y (Spi1y) 26.03.12 12:17
Извиняюсь, как говориться, поспешишь - людей насмешишь. В предыдущем сообщении спутал понятия массивы и структуры. Массив разобрал, еще проще выходит:

{"#",51e7a0d2-530b-11d4-b98a-008048da3034,{КоличествоЭлементов,{ОписаниеЗначения1}, ... , {ОписаниеЗначенияN}}}

И действительно, для вложенных массивов достаточно в описание значения вместо строки {ОписаниеТипа,Значение} передать строку {ОписаниеМассива}, сформированную аналогично.
33. igor (igor_kav) 26.03.12 16:58
Spi1y, Спасибо! ОЧЕНЬ помогли!
34. Spi1y (Spi1y) 26.03.12 17:25
35. igor (igor_kav) 30.03.12 16:55
Пару функций удалось сделать и использовать в 1С, но написал третью функцию в dll... при попытке использования в 1с именно этой третьей функции, 1с вылетает с ошибкой "Программа 1Сv8 не работает Возникшая проблема привела к прекращению работы программы. бла-бла". Самое интересное, что для тестирования создал проект VLC на delphi, поместил в него код функции. В VLC-проекте ФУНКЦИЯ РАБОТАЕТ!

Какие есть варианты решения?
36. Александр Соломатин (v77) 30.03.12 17:17
37. igor (igor_kav) 30.03.12 17:24

library aukro_soap;

uses
  SysUtils,
  Classes,
  DateUtils,
  InvokeRegistry,
  Rio,
  SOAPHTTPClient,
  v8napi,
  uploader;

{$R *.res}

type

TMyClass = class(TV8UserObject)
  private
     RIO           : THTTPRIO;
     country_id    : Integer;
     local_version : Int64;
  public
    function doLogin(RetValue: PV8Variant; Params: PV8ParamArray; const ParamCount: integer): boolean;
    function getMyData(RetValue: PV8Variant; Params: PV8ParamArray; const ParamCount: integer): boolean;
    function getCatsList(RetValue: PV8Variant; Params: PV8ParamArray; const ParamCount: integer): boolean;
    constructor Create; override;
end;

{ TMyClass }

function TMyClass.doLogin(RetValue: PV8Variant; Params: PV8ParamArray; const ParamCount: integer): boolean;
var
  user_login          : string;
  user_password       : string;
  webapi_key          : string;
  info                : string;
  ver_key             : Int64;
  session_handle_part : string;
  user_id             : Int64;
  server_time         : Int64;
begin
  // получаем параметры функции
  user_login    := V8AsAString(@Params[1]);
  user_password := V8AsAString(@Params[2]);
  webapi_key    := V8AsAString(@Params[3]);

  try
    (RIO as AllegroWebApiPortType).doQuerySysStatus(local_version, country_id, webapi_key, info, ver_key);
    (RIO as AllegroWebApiPortType).doLogin(user_login, user_password, country_id, webapi_key, ver_key, session_handle_part, user_id, server_time);

    V8SetWString(RetValue, session_handle_part); // устанавливаем результат функции
    result := True;
  except
    result := False;
  end;
end;

// ФУНКЦИЯ НЕ РАБОТАЕТ !!! СКОРЕЕ ВСЕГО УТЕЧКА ПАМЯТИ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ STRING
function TMyClass.getMyData(RetValue: PV8Variant; Params: PV8ParamArray; const ParamCount: integer): boolean;
var
  session_handle_part    : string;
  user_data              : UserDataStruct;
  invoice_data           : InvoiceDataStruct;
  company_extra_data     : CompanyExtraDataStruct;
  company_second_address : CompanySecondAddressStruct;
  pharmacy_data          : PharmacyDataStruct;
  alcohol_data           : AlcoholDataStruct;
  related_persons        : RelatedPersonsStruct;
  ResultString           : WideString;
begin
  // получаем параметры функции
  session_handle_part    := V8AsAString(@Params[1]);
  // инициализируем переменные
  user_data              := UserDataStruct.Create;
  invoice_data           := InvoiceDataStruct.Create;
  company_extra_data     := CompanyExtraDataStruct.Create;
  company_second_address := CompanySecondAddressStruct.Create;
  pharmacy_data          := PharmacyDataStruct.Create;
  alcohol_data           := AlcoholDataStruct.Create;
  related_persons        := RelatedPersonsStruct.Create;

  try
    (RIO as AllegroWebApiPortType).doGetMyData(session_handle_part, user_data, invoice_data, company_extra_data,
                                               company_second_address, pharmacy_data, alcohol_data, related_persons);

    ResultString := '{"#",4238019d-7e49-4fc9-91db-b6b951d5cf8e,{22,';
    ResultString := ResultString + '{{"S","user_id"},{"N",'+IntToStr(user_data.user_id)+'}},';
    ResultString := ResultString + '{{"S","user_login"},{"S","'+user_data.user_login+'"}},';
    ResultString := ResultString + '{{"S","user_rating"},{"N",'+IntToStr(user_data.user_rating)+'}},';
    ResultString := ResultString + '{{"S","user_first_name"},{"S","'+user_data.user_first_name+'"}},';
    ResultString := ResultString + '{{"S","user_last_name"},{"S","'+user_data.user_last_name+'"}},';
    ResultString := ResultString + '{{"S","user_maiden_name"},{"S","'+user_data.user_maiden_name+'"}},';
    ResultString := ResultString + '{{"S","user_company"},{"S","'+user_data.user_company+'"}},';
    ResultString := ResultString + '{{"S","user_country_id"},{"N",'+IntToStr(user_data.user_country_id)+'}},';
    ResultString := ResultString + '{{"S","user_state_id"},{"N",'+IntToStr(user_data.user_state_id)+'}},';
    ResultString := ResultString + '{{"S","user_postcode"},{"S","'+user_data.user_postcode+'"}},';
    ResultString := ResultString + '{{"S","user_city"},{"S","'+user_data.user_city+'"}},';
    ResultString := ResultString + '{{"S","user_address"},{"S","'+user_data.user_address+'"}},';
    ResultString := ResultString + '{{"S","user_email"},{"S","'+user_data.user_email+'"}},';
    ResultString := ResultString + '{{"S","user_phone"},{"S","'+user_data.user_phone+'"}},';
    ResultString := ResultString + '{{"S","user_phone2"},{"S","'+user_data.user_phone2+'"}},';
    ResultString := ResultString + '{{"S","user_ss_status"},{"N",'+IntToStr(user_data.user_ss_status)+'}},';
    ResultString := ResultString + '{{"S","site_country_id"},{"N",'+IntToStr(user_data.site_country_id)+'}},';
    ResultString := ResultString + '{{"S","user_junior_status"},{"N",'+IntToStr(user_data.user_junior_status)+'}},';
    ResultString := ResultString + '{{"S","user_birth_date"},{"N",'+IntToStr(user_data.user_birth_date)+'}},';
    ResultString := ResultString + '{{"S","user_has_shop"},{"N",'+IntToStr(user_data.user_has_shop)+'}},';
    ResultString := ResultString + '{{"S","user_company_icon"},{"N",'+IntToStr(user_data.user_company_icon)+'}},';
    ResultString := ResultString + '{{"S","user_is_allegro_standard"},{"N",'+IntToStr(user_data.user_is_allegro_standard)+'}}}}';

    V8SetWString(RetValue, ResultString); // устанавливаем результат функции
    result := True;
  except
    result := False;
  end;
end;

function TMyClass.getCatsList(RetValue: PV8Variant; Params: PV8ParamArray; const ParamCount: integer): boolean;
var
  webapi_key    : string;
  cats_list     : ArrayOfCats;
  ver_key       : Int64;
  ver_str       : string;
  CurrCats      : CatInfoType;
  ResultString  : WideString;
begin
  // получаем параметры функции
  webapi_key    := V8AsAString(@Params[1]);
  // инициализируем переменные
  CurrCats      := CatInfoType.Create;

  try
    (RIO as AllegroWebApiPortType).doGetCatsData(country_id, local_version, webapi_key, cats_list, ver_key, ver_str);

    // формируем массив из структур для 1С, затем в 1С необходимо использовать функцию "ЗначениеИзСтрокиВнутр()"
    ResultString := '{"#",51e7a0d2-530b-11d4-b98a-008048da3034,{'+IntToStr(Length(cats_list));
    for CurrCats in cats_list do
    begin
      ResultString := ResultString + ',{"#",4238019d-7e49-4fc9-91db-b6b951d5cf8e,{4,{{"S","cat_id"},{"S","'+IntToStr(CurrCats.cat_id)+'"}},';
      ResultString := ResultString + '{{"S","cat_name"},{"S","'+CurrCats.cat_name+'"}},';
      ResultString := ResultString + '{{"S","cat_parent"},{"S","'+IntToStr(CurrCats.cat_parent)+'"}},';
      ResultString := ResultString + '{{"S","cat_position"},{"S","'+IntToStr(CurrCats.cat_position)+'"}}}}';
    end;
    ResultString := ResultString + '}}';

    V8SetWString(RetValue, ResultString); // устанавливаем результат функции
    result := True;
  except
    result := False;
  end;
end;

constructor TMyClass.Create;
begin
  RIO := THTTPRIO.Create(nil);
  RIO.WSDLLocation := 'http://webapi.allegro.pl/uploader.php?wsdl';
  RIO.Service      := 'AllegroWebApiService';
  RIO.Port         := 'AllegroWebApiPort';

  country_id       := 209; // 209 - Украина; 228 - Neverland (webapi) для тестового сервиса http://testwebapi.pl
  local_version    := 1;
end;


begin

  with ClassRegList.RegisterClass(TMyClass, 'MySuperExtention', 'TMyClass') do
  begin
    // регистрируем функции
    AddFunc('doLogin',         'Авторизироваться',        @TMyClass.doLogin,         3);
    AddFunc('getMyData',       'ПолучитьМоиДанные',       @TMyClass.getMyData,       1);
    AddFunc('getCatsList',     'ПолучитьСписокКатегорий', @TMyClass.getCatsList,     1);
  end;

end.
...Показать Скрыть
38. igor (igor_kav) 30.03.12 18:10
поставил исключение в процедуре _CallAsFunc и получил ошибку:

Внешняя компонента : Invalid pointer operation.
Ошибка! {Форма.Форма.Форма(473)}: Ошибка при вызове метода контекста (ПолучитьМоиДанные): Ошибка внешней компоненты
39. Александр Соломатин (v77) 30.03.12 18:35
(38) ну вроде всё правильно. смотри в отладчике.
40. igor (igor_kav) 30.03.12 18:40
41. igor (igor_kav) 30.03.12 18:53
Прочитал, что СКОРЕЕ ВСЕГО УТЕЧКА ПАМЯТИ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ STRING, но как решить ума не приложу...

Кто сталкивался, ПОМОГИТЕ!
43. igor (igor_kav) 31.03.12 01:25
выдает ошибку External exception C000001D на строке:
(RIO as AllegroWebApiPortType).doGetMyData(session_handle_part, user_data, invoice_data, company_extra_data,
                                             company_second_address, pharmacy_data, alcohol_data, related_persons);


Но только в DLL, в EXE все нормально работает. В чем же все-таки причина?
44. igor (igor_kav) 31.03.12 15:01
Можно ли передать функции параметр типа ТаблицаЗначений или XDTO пакет и как его потом в delphi разобрать?
45. Александр Соломатин (v77) 31.03.12 16:39
(43) причина в ошибке. надо смотреть в отладчике. вышли мне исходники, я гляну. у тебя delphi 7?
46. igor (igor_kav) 31.03.12 16:44
(45) спасибо! :) ошибку нашел! все, как всегда, было банально просто. RIO не освобождал.
Спасибо за проделанную работу, очень нужную вещь ВК NativeAPI на Delphi создали.
47. Александр Соломатин (v77) 31.03.12 16:50
48. Andrew V (0xe0) 05.07.12 14:04
Александр, из компоненты (*в вашей реализации) есть возможность обращаться к методам интерфейса 1С?
49. Сергей Вн (EmpireSer) 10.08.12 01:34
Объясните мне - зачем нужна структура "ТV8ObjectRec" ?
50. Владислав Ярославлев (vladon) 25.09.12 15:46
На сервере x64 не работает, к сожалению. Ковыряю-ковыряю код, не пойму, в чём дело.
51. Александр Соломатин (v77) 26.09.12 08:34
Я на 64 не пробовал. Может так заработает(см. прикрепленный файл)
Прикрепленные файлы:
v8napi.zip
52. Владислав Ярославлев (vladon) 26.09.12 15:22
(51) v77, это из оригинальных исходников от Александра Соломатина? Нет, тоже не получается.
53. Александр Соломатин (v77) 26.09.12 15:55
Ну у меня нету сервера 64. пока ничем не могу помочь.
54. Александр Соломатин (v77) 26.09.12 15:56
(52) vladon, а на клиенте 64 работает?
55. Александр Соломатин (v77) 26.09.12 15:59
(52) vladon, а как не работает? в чем компилировалось?
56. Владислав Ярославлев (vladon) 26.09.12 16:01
(54) v77, клиента 64 же не существует.

компилировалось Delphi XE2 и Delphi XE3.
57. Александр Соломатин (v77) 26.09.12 21:22
(56) vladon, ну и как не работает то. в чем это не работает проявляется?
58. Владислав Ярославлев (vladon) 26.09.12 22:34
(57) v77, вот здесь лежит архив со всеми исходниками: http://narod.ru/disk/61615376001.5ca45c99a6ebdc7d919aa57124f0aa7b/SocketNative.zip.html

в каталоге 1С есть .dt-шник, это база, где в общий макет залиты dll-ки с манифестом в зипе, dll-ки откомпилены delphi xe3, в любом случае все исходники там же

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

так вот, на 32-бит сервере компонента подключается - всё нормально отрабатывает
на 64-бит сервере при нажатии кнопки "Подключить компоненту" сервер долго-долго думает, а потом клиент вылетает с сообщением, что сервер принудительно закрыл подключение.

в любом случае, если есть возможность, попробуйте сами.
59. Александр Соломатин (v77) 29.09.12 23:56
(58) vladon, попробуй такой вариант. у меня вроде работает. на сервере не проверял(нету у меня). проверял тестовой программой, которая загружает dll и читает список методов и свойств ВК. старая твоя ВК не грузилась, теперь стала грузиться. в архиве вариант модуля v8napi.pas. отпишись заработало или нет.
60. Александр Соломатин (v77) 29.09.12 23:57
61. Владислав Ярославлев (vladon) 01.10.12 08:50
(60) v77, огромное спасибо, работает.
62. andrewks 20.10.12 21:36
какова лицензия на исходный код? возможно ли его использование в проектах под лицензией GPL v2/3?
63. Александр Соломатин (v77) 22.10.12 10:19
Да используйте где хотите.
64. andrewks 23.10.12 09:14
(63) v77, не сочтите за наглость, но, так сказать, во избежание возможных недоразумений, можно при следующем обновлении в программных модулях указать тип лицензии на исходный код? например, Apache 2.0 (наиболее предпочтительная и либеральная), X11, или Modified BSD (неограниченное использование). или двойную лицензию GPL v2 и GPL v3 (на выбор пользователя).

хотим тут один небольшой проектик замутить на базе модуля для FreePascal под лицензией GPL v2, в целях экономии времени на рутину хотим использовать Ваш модуль ;-)

спасибо.
65. 11 22 (eoego1) 20.11.12 17:55
Мегаценная вещь, спасибо автору большое! Но возник вопрос, мне очень нужно сделать так, чтобы во время работы какой либо одной функции вызванной по nativeapi из 1С, произошла передача данных (к примеру установка свойства формы или генерация внешенего события с передачей данных в 1С). Например:

//процедура вызываемая из 1С
function TMyClass.SleepFunc(RetValue: PV8Variant; Params: PV8ParamArray; const ParamCount: integer; var v8:TV8AddInDefBase): boolean;
var
ms: Integer;
begin
ms := V8AsInt(@Params[1]); // к примеру 100.000
//тут хочу вызвать исключение в 1С и передать в него строку "Привет я пошел спать!" или как-то иначе
sleep(ms);
//допустим тут еще раз хочу вызвать исключение
//или установить свойство заголовка на форме или переменной модуля 1С. "Привет я проснулся!"
result := True; //завершается вызванная функция
end;
После некоторых исследований, было установлено, что к примеру если вызвать во время работы функции sleep (или любой другой) функцию, например, вызова внешнего события, то оно генерируется не в то время, где я вызываю ExternalEvent, а только по выходу из основной функции. То есть у меня никак не получается передавать в 1С, например строку промежуточного результата работы функции во время ее работы. Все уходит в 1С только по выходу из нее. Как решить подобную задачу?
66. andrewks 26.11.12 17:38
в модуле для FPC не нашёл функцию V8SetPWideChar ( возврат в 1С строки, представленной в FPC типом PWideChar )

дописал. может, кому, пригодится:
function TV8UserObject.V8SetPWideChar(V: PV8Variant;
  Value: PWideChar): boolean;
var
  L, SZ: longword;
begin

  result := (Value = nil);
  if result then
    Exit;

  V8ClearVar(V);
  V.vt := VTYPE_PWSTR;
  L := Length(Value);
  SZ := (L + 1) * SizeOf(WideChar);

  result := V8MM.AllocMemory(@(V.VarEnum.vtRecWideString.pwstrVal), SZ);
  if result then
  begin
    Move(Value^, V.VarEnum.vtRecWideString.pwstrVal^, SZ);
    V.VarEnum.vtRecWideString.wstrLen := L;
  end;
end;

...Показать Скрыть
67. andrewks 29.11.12 23:45
в модуле для FPC ошибка в function _GetParamDefValue, вызывающая падение в случае, если параметры по умолчанию не заданы, а 1с видит, что методу передано меньше параметров и пытается запросить параметр по умолчанию

правильный вариант кода:

function _GetParamDefValue(Obj: PV8ObjectRec; const lMethodNum,
  lParamNum: integer; pvarParamDefValue: PV8Variant): boolean; stdcall;
var
ind: integer;
begin
  result := False;
  if Obj.RelObj1.ClassReg.MethList[lMethodNum].DefParams <> nil then
  begin
    for ind := 0 to length(Obj.RelObj1.ClassReg.MethList[lMethodNum].DefParams.Values)-1 do
    begin
      if (Obj.RelObj1.ClassReg.MethList[lMethodNum].DefParams.Values[ind].Num = lParamNum) then
      begin
        pvarParamDefValue^ := Obj.RelObj1.ClassReg.MethList[lMethodNum].DefParams.Values[ind].Value;
        result := True;
      end;
    end;
  end;
end;

...Показать Скрыть
68. Александр Соломатин (v77) 30.11.12 09:11
(67) andrewks, Спасибо. Исправлю.
69. andrewks 19.12.12 21:23
что-то не ясен момент: в описании технологии Native API сказано, что BLOB (Двоичные данные) могут только возвращаться из компоненты в 1С, про передачу BLOB из 1С в компоненту ничего не сказано. при попытке передать ДвоичныеДанные в параметре метода 1С ругается на неверный параметр (до компоненты даже дело не доходит).
однако в Вашем модуле есть функция по получению BLOB V8AsBlob(). У Вас получилось передать ДвоичныеДанные в компоненту? не поделитесь рецептом?
70. Александр Соломатин (v77) 20.12.12 08:29
(69) andrewks, я не помню, что пробовал. ну если не дает, то значит нельзя. А V8AsBlob() наверное на всякий случай сделал.
71. Осипов Сергей (fixin) 20.12.12 18:07
72. andrewks 11.01.13 08:25
73. UncleVader (UncleVader) 24.01.13 12:12
Раз уж добавили поддержку Lazarus, может попробуем и под Linux скомпилить?
Вот тут есть готовая виртуальная машина с установленным Lazarus, попробовал в нем скомпилить выложенную демку, но она не подключается в контексте сервера 1С под x64 Ubuntu. Есть мысли? Спасибо!
74. Александр Соломатин (v77) 24.01.13 12:30
Мыслей нет. А что нибудь другое подключается в контексте сервера 1С под x64 Ubuntu?
75. andrewks 24.01.13 12:34
(73) UncleVader, там же написано, что под Android
76. UncleVader (UncleVader) 24.01.13 12:44
(74) v77, У меня нет к сожалению ни одной ВК под linux, поэтому трудно сказать, дал бы кто попробовать...
(75) andrewks, ну и что, главное что стоит настроенный Lazarus и компилит, в т.ч. и приложенный тут пример ВК
77. andrewks 24.01.13 12:48
(76) UncleVader, я к тому, что если у Вас есть доступ к серваку с убунтой х64, то, может, стоит скомпилить прямо на нём? у меня на ноуте стоит убунта, но она там х32
78. UncleVader (UncleVader) 24.01.13 12:57
(77) andrewks, Чтоб на нем скомпилить туда надо поставить Lazarus, а для меня это китайская грамота ((
Во вложении скомпиленная в упомянутой (73) системе, попробуйте может у Вас подключится
Прикрепленные файлы:
libdemo.so
79. UncleVader (UncleVader) 24.01.13 17:23
Поставил 64 Ubuntu, на него Lazarus, скомпилил пример - на сервере не подключается ((
80. Misha ⁠ (Magister) 10.02.13 02:39
81. serg_121 (SerG_121) 11.02.13 13:53
Почему когда я создаю поток у меня вылетает ошибка? В чем проблема? Код в прекрепленных файлах
Прикрепленные файлы:
1cComPort.rar
82. Александр Соломатин (v77) 11.02.13 14:11
Ну ты в отладчике посмотри где глючит. А ProcessMessages тебе зачем? Поставь вместо ProcessMessages sleep(0) для начала.
83. serg_121 (SerG_121) 11.02.13 15:39
(82)Я так и со слипом пробовал бесполезно! Попробуй у себя проверить мой код.
Выдает ошибку и вылетает 1с именно когда запускается поток ReadThread
84. andrewks 11.02.13 16:12
(83) SerG_121, видимо, у Вас исключение вылетает. попробуйте в try/except и выводить лог, может, прояснится
85. Александр Соломатин (v77) 11.02.13 16:46
(83) SerG_121, Ты создаешь объект в 1с. Выполняешь его метод ОткрытьПорт. В методе ОткрытьПорт создается поток, который использует объект. Но объект после выполнения ОткрытьПорт автоматически убивается, но в потоке к нему есть обращение в Execute. Обращение к несуществующему объекту. Наверное по этому и глючит.
86. serg_121 (SerG_121) 12.02.13 07:38
(85)Может подскажешь как реализовать?
87. Александр Соломатин (v77) 12.02.13 08:38
А чего надо реализовать?
88. serg_121 (SerG_121) 12.02.13 08:47
(87)Спасибо большое все разобрался )
89. Дмитрий Ерохин (TamDE) 26.02.13 20:11
Собрал ВК в Lazarus.
Нашел небольшой глюк: если передать в функцию ФункцияПривет2 пустые строки, то платформа "валится"
//Рез = Об.ФункцияПривет2("Раз","Два");
Рез = Об.ФункцияПривет2("","");

Обошел путем добавления условия
    
if L > 0 then

перед строкой
       
Move(Value[1], V.VarEnum.vtRecWideString.pwstrVal^, SZ);

в методе V8SetWString
90. Misha ⁠ (Magister) 04.03.13 01:39
В Linux таки не работает.
Платформа грузит .so, вызывает несколько функций и валится по SIGSEGV.
Вот что успевает вызвать:
[quote]
GetClassNames
GetClassObject
_setMemManager
_GetInfo
[/quote]
После этого падение. Пока причину понять не смог, может быть будут идеи?
91. Александр Соломатин (v77) 04.03.13 08:58
(90) Magister, есть идея посмотреть в отладчике. линуксов у меня нету.
92. Misha ⁠ (Magister) 05.03.13 01:48
(91) Отладчик ловит исключение, и в качестве адреса показывает нулевые адреса. Бред полный :)
Ещё немного поразбирался - судя по всему причина в том, что под Linux 1С компилируется с использованием GCC, а у него виртуальная таблица методов в памяти имеет другую структуру.
Получается что "грязный" хак, с помощью которого вообще работает эта библиотека не срабатывает, т.к. TV8ProcRec не соответствует IComponentBase.

Пока что удалось добиться таки вызова RegisterExtensionAs добавлением парочки пустых полей с типом Pointer, но теперь другая проблема - V8MM.AllocMemory() возвращает false...
93. andrewks 05.03.13 08:30
(89) TamDE, что-то не так в Вашем королевстве.
1. эта функция отвечает за возвращаемые значения, а не за передаваемые
2. L не может быть равно 0
3. у меня падения на пустых строках нет
94. andrewks 05.03.13 08:35
(92) Magister, а Вы на какой платформе, и на каком дистре лин тестируете?
95. Misha ⁠ (Magister) 05.03.13 18:43
(94) Ubuntu 12.10 x32, 1C 8.3.2 x32 файловая.
На Windows с тем же релизом 1С всё хорошо.
96. andrewks 07.03.13 22:10
(95) Magister, немного наблюдений:

в Win 1с вызывает функции в таком порядке:
Initialization
GetClassObject()
_Init()
_setMemManager()
_SetLocale()
_GetInfo()
_RegisterExtensionAs()
...
_Done()
DestroyObject()
Finalization

в Lin:
Initialization
GetClassObject()
_setMemManager()
_GetInfo()
далее - падение до захода в _RegisterExtensionAs()

почему-то в линуксе обходится стороной _Init()
97. andrewks 08.03.13 00:00
(92) Magister, похоже, проблема с менеджером памяти. только у меня при попытке вызова AllocMemory() - сразу крах. пытаюсь в _setMemManager() вызвать AllocMemory() - в винде успешно, память выделяется, в лин - сразу крах.

что-то с описанием интерфейса, может? соглашение о вызове, думаю, тут ни при чём
98. Misha ⁠ (Magister) 08.03.13 04:24
Просто структура класса не такая получается. Компилятор другой - вот и всё, баста.
Думаю, правильным путем было бы создание "обертки" на C++, которая бы уже общалась с FreePascal. Иначе гиблое это дело, как мне кажется...
Сейчас вот добился вызова методов:
[quote]GetClassNames
GetClassObject
_Init
_setMemManager
_RegisterExtensionAs[/quote]
Вот откуда тут _RegisterExtensionAs? Ведь, судя по логике, должен быть _SetLocale.
Вывод - в том месте, где у нас находится _RegisterExtensionAs, должен находится _SetLocale.
Это, в принципе, объясняет и падение на RegisterExtensionAs - т.к. SetLocale по параметрам отличается.

upd. Да, так и есть. Подставил туда _SetLocale - получил параметром строку своей локали. Т.е. я всё правильно понял.
99. andrewks 08.03.13 08:55
(98) Magister, эмм... если я правильно понимаю, то достаточно найти правильный порядок адресов в TV8ProcRec, зачем обёртка?
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа