Имя: Пароль:
1C
1С v8
v8: ВК NativeAPI и Delphi - Invalid pointer operation
0 igor_kav
 
30.03.12
20:32
Для написания ВК использую NativeAPI (http://infostart.ru/public/81644/).

Пару функций удалось сделать и использовать в 1С, но написал третью функцию в dll... при попытке использования в 1с именно этой третьей функции, 1с вылетает с ошибкой "Программа 1Сv8 не работает Возникшая проблема привела к прекращению работы программы. бла-бла". Самое интересное, что для тестирования создал проект VLC на delphi, поместил в него код функции. В VLC-проекте ФУНКЦИЯ РАБОТАЕТ!

Поставил исключение в процедуре _CallAsFunc и получил ошибку:

Внешняя компонента : Invalid pointer operation.
Ошибка! {Форма.Форма.Форма(473)}: Ошибка при вызове метода контекста (ПолучитьМоиДанные): Ошибка внешней компоненты

Прочитал, что СКОРЕЕ ВСЕГО УТЕЧКА ПАМЯТИ ИЗ-ЗА ИСПОЛЬЗОВАНИЯ STRING, но как решить ума не приложу...

Кто сталкивался, ПОМОГИТЕ!
1 igor_kav
 
30.03.12
20:43
вот код

[code]
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.
[/code]
2 igor_kav
 
30.03.12
20:44
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.
3 igor_kav
 
30.03.12
20:46
не могу нормально скопировать код ВК. вот ссылка на комментарии к NativeApi http://forum.infostart.ru/forum24/topic38092/, там есть мой код ВК
4 romix
 
30.03.12
20:47
Вот еще дельфийский пример http://infostart.ru/public/88060/
5 igor_kav
 
30.03.12
21:04
Я смотрел Вашу работу, от туда и взял код на обработку исключения :), но увы, смог выявить только ошибку, а вот как ее исправить ума не приложу. Что можете посоветовать?
6 romix
 
30.03.12
21:21
(5) Попробуйте ее как шаблон использовать - там больше функций, и я что-то исправлял (уже не помню что).
7 romix
 
30.03.12
21:22
Т.е. не меняя числа функций - а то может где-то чего-то забыли там изменить под новое число функций.
8 vmv
 
30.03.12
21:37
(0) 1С очень критичка к г-коду самопальных библиотек, ведь разработчики платформы далеко не глупы
9 igor_kav
 
30.03.12
21:42
(6) Взял полностью Ваш переработанный модуль v8napi, то теперь 1С вываливаентся при вызове любой функции :(
10 igor_kav
 
31.03.12
01:28
Отладчиком выявил ошибку "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 все нормально работает. В чем же все-таки причина?
11 H A D G E H O G s
 
31.03.12
01:45
Фиг тя знает..

ЗначениеИзСтрокиВнутр - фиии, реальне пацаны юзают XDTO.
У меня даже объекты для формирования строкого возврата Массива, СпискаЗначений и Структуры есть.

Вот темка:
v8: Сериализация СпискаЗначений В XDTO. Где я не прав?
12 H A D G E H O G s
 
31.03.12
01:48
Вообще - ужастный адскый код.
13 H A D G E H O G s
 
31.03.12
01:48
THTTPRIO - че за зверь, неужели типовые Indyйцы не устаривают?
14 igor_kav
 
31.03.12
01:54
THTTPRIO использую для работы с веб-сервисом, одно непонятно почему в EXE работает, а вот в DLL ну НИКАК?
15 H A D G E H O G s
 
31.03.12
02:21
Попробуй тупо после try, Перед (RIO as AllegroWebApiPortType).doGetMyData(....

написать
CoInitializeEx(nil, COINIT_MULTITHREADED);
16 igor_kav
 
31.03.12
09:31
(15) попробовал, результат нулевой :(
Какие еще будут варианты?
17 romix
 
31.03.12
14:18
Вариант - взять работающую DLL и не меняя  в ней число функций запустить в одной из них свою требуемую функцию. Тогда станет ясно в чем проблема - в коде обвязки или в коде функции.

Или наоборот - заменить содержимое своей функции на что-то нейтральное типа sleep или MessageBox, и посмотреть а будет ли работать так. Если нет то неправильно написана обвязка, если да - то пошагово проверять свою функцию (например повтыкать везде MessageBox-ы для отладки, на каком споткнется там и ошибка.
18 igor_kav
 
31.03.12
15:16
(11) Как передать функции XDTO пакет (ТаблицаЗначений), а потом его в delphi разобрать?
Компьютер — устройство, разработанное для ускорения и автоматизации человеческих ошибок.