На главную... Продукты | Технологии | Классификаторы | Проекты | Скачать | Цены| Форум | Статьи | Обучение | Контакты

ГИС Оператор 11 > Получение идентификатора пользовательской карты

Поиск  Пользователи  Правила  Войти
Форум » Настольные приложения » GIS ToolKit, GIS ToolKit Active, ГИС Конструктор для Windows
Страницы: 1
RSS
ГИС Оператор 11 > Получение идентификатора пользовательской карты
 
Добрый день,

Имеется карта с расширением .SIT. В своей прикладной задаче я создаю свою карту по параметрам имеющейся через mapCreateAndAppendSite. Карта создается и в операторе видно, что теперь 2 карты в одной. Я пытался получить идентификатор созданной карты серез mapOpenSiteForMap и вроде как получаю какое-то значение, но если я пытаюсь создать объект на карте с этим идентификатором, то получаю exception.

Что я делаю не так?
 
По идее, после  вызова функци mapCreateAndAppendSite я должен был получить идентификатор созданной карты, но при попытке использовать этот идентификатор вылетает exception: Project Operator.exercise raised exeception class $C0000005 access violation at 0x0241c741:read of address 0x00000023.
 
В задаче сперва проверяется наличие нашей карты, если она отсутствует, то задача её создает:
Код
  function GetMapHandle(Map : HMap): HMap;  var    tMap : HMap;    name : PAnsiChar;    newMap,newRsc : AnsiString;    I : Integer;
  begin
    name := mapGetMapPath(Map);
    I := Length(name) - 1;
    while name[I] <> '\' do
      begin
        I := I - 1;
      end;
    newMap := AnsiString(name);
    Delete(newMap,(I+2),Length(name)+5);
    newRsc := newMap;
    Insert(MapName,newMap,Length(newMap)+1);
    Insert(RscName,newRsc,Length(newRsc)+1);
    if not FileExists(newMap) then
    begin      tMap := CreateMap(Map,PAnsiChar(newMap),PAnsiChar(newRsc));
    end
    else
    begin
      tMap := mapOpenSiteForMap(Map,PAnsiChar(newMap),0);
    end;
    Result := tMap;
  end;
  function CreateMap(Map : HMap;NewMap : PAnsiChar; NewRsc : PAnsiChar): HMap;
  var
    tMap : HMap;
    tSite : TCreateSite;
    MR : TMAPREGISTER;
    LR : TLISTREGISTER;
    I : integer;
    name : PAnsiChar;
  begin
    name := mapGetMapName(Map);
    mapGetMapInfo(Map,0,MR,LR);
    tSite.Length := MR.Length;
    FillChar(tSite.MapName, sizeof(tSite.MapName),0);
    for I := 0 to Length(name) do
    begin
      tSite.MapName[I+1] := name[I];
    end;
    tSite.MapType := MR.MapType;
    tSite.MaterialProjection := MR.MaterialProjection;
    tSite.Scale := MR.Scale;    tSite.FirstMainParallel := MR.FirstMainParallel;
    tSite.SecondMainParallel := MR.SecondMainParallel;    tSite.AxisMeridian := MR.AxisMeridian;
    tSite.MainPointParallel := MR.MainPointParallel;
    try
      tMap := mapCreateAndAppendSite(Map,NewMap,NewRsc,tSite);
      Result := tMap;
    except
      on E:Exception
        do begin
          ShowMessage(E.Message);
          Result := 0;
        end;
      end;
   end;
 
На первый взгляд, Ваш код не содержит ошибок в части использования MAPAPI.

Исключение exeception class $C0000005 - это, как правило, исключение среды разработки, в большинстве случаев являющееся следствием повреждения памяти где-то в программе. Этот экскепшн, например, может встречаться в режиме отладки и не проявляться при сборке в release (или наоборот). Надо искать место, где портиться память.

Если mapCreateAndAppendSite возвращает ненулевой результат, значит функция отработала. Скорее всего, память повреждается в другом месте. Или до, или после.
Непосредственно определить, отработала ли функция можно проверив наличие созданной карты на диске - NewMap.

Для начала я бы проверил этот фрагмент:
Код
    for I := 0 to Length(name) do    begin
      tSite.MapName[I+1] := name[I];
    end;
Тут tSite.MapName - это массив из 32-х однобайтовых символов, I := 0 to Length(name)  не проверяется на превышение этого предела.


Это в принципе не верно:
Код
tSite.Length := MR.Length;
sizeof(TCreateSite) не равен sizeof(TMAPREGISTER).


Далее следует по максимуму анализировать коды возврата от функций.
В частности mapGetMapInfo скорее всего не отработает, так как нумерация листов начинается с 1, а Вы указываете 0.
В этом случае код возврата будет равен 0, а структуры  MR : TMAPREGISTER и LR : TLISTREGISTER останутся непроинициализированными и могут содержать грязь.


Также повреждения памяти могут быть в других фрагментах кода, который тут не представлен.


Просьба на будущее - указывать версию среды разработки, версию GIS ToolKit и версию библиотек ГИС-ядра (gisacces.dll), а также под какую ОС какой разрядности ведется разработка.
Также следует уточнить, Вы разрабатывает отдельное приложение или прикладную задачу для работы в ГИС Панорама или ГИС Оператор.


Цитата
но при попытке использовать этот идентификатор
А как именно используется идентификатор?
 
Спасибо за развернутый ответ, Денис.

Разрабатывается прикладная задача для ГИС Оператор 11. За основу взят образец с sdk11. 32 разрядная версия.

Мне удалось получить доступ к созданию объектов на новой карте через mapOpenMap. Как-то не сразу дошло до меня его использовать.

tSite.MapName не может быть превышен, т.к. берется с основой карты.

tSite.Length я не знаю какой размер задать, т.к. не создаю структуры TCREATESITE.

mapGetInfo срабатывала и с 0. Карта всеже создается и имеет те же параметры, что и основная.
 
Цитата
Евгений написал:
tSite.MapName не может быть превышен, т.к. берется с основой карты.
Не гарантированно. Всегда лучше проверять. Рекомендуется использовать более безопасные функции, заполняющие выделенный Вами буфер с контролем заданного размера, например, mapGetMapNameEx.
Имя карты в паспорте с ограничением в 32 символа - это, можно сказать, устаревшее поле в паспорте карты. Паспорт карты имеет возможность хранить и более длинное имя (смотря какая функция используется при создании), и даже имя в кодировке юникод. Поэтому, какой длины имя Вам вернулось, лучше все-таки проверить.

Цитата
Евгений написал:
tSite.Length я не знаю какой размер задать, т.к. не создаю структуры TCREATESITE.
В Delphi указание в разделе VAR переменной заданного типа - "tSite : TCreateSite" - это и есть объявление локальной переменной типа TCreateSite, то есть реально выделение под нее памяти в стеке.
Вы же используете остальные поля этой структуры.
Поле Length используется для контроля, причиной Вашего exeception это не является, но это поле подлежит заполнению.
tSite.Length := sizeof(tSite);

Цитата
Евгений написал:
Разрабатывается прикладная задача для ГИС Оператор 11. За основу взят образец с sdk11. 32 разрядная версия.
Тогда все немного сложнее.
Тут могут быть дополнительные ошибки в процессе "прикручивания" задачи к ГИС Оператору.
Кроме того, поскольку Вы пишете на Delphi, надо смотреть корректность объявления прототипов функций (проверять на предмет их соответствия заголовочным файлам ядра в части объявления параметров и стандартов вызова).
Заголовочные файлы содержатся в SDK в директории  .\Include.

Примеры, как правильно должны выглядеть прототипы Вы можете посмотреть в исходных текстах GIS ToolKit (см. файлы *.inc).

В примерах в SDK для ГИС Оператора могут оказаться прототипы для Delphi6 - Delphi7:
Код
function mapCreateAndAppendSite(map : HMAP;
                       const mapname:PChar;const rscname:PChar;
                       var createsite : TCREATESITE):HMap;  stdcall;
  external sGisAcces name 'mapCreateAndAppendSite';
Если Вы используете Delphi XE2 и выше, то тип PChar будет означать уже не указатель на строку в однобайтовой (ANSI) кодировке, а указатель на Unicode-строку.

Также необходимо следить, чтобы Вы работали именно с той библиотекой mapacces.dll, с которой работает ГИС Оператор.


А вообще ошибка exeception class $C0000005 может быть следствием очень и очень многих причин. Начиная от ошибок в коде (как правило рушащих память), заканчивая ошибками самой среды разработки (некорректная инсталляция, не крайний сервис-пак, ошибки в работе CodeGuard и т.д.).
Также при разработке динамических библиотек эта ошибка возможна в следствие разных runtime-библиотек разрабатываемой DLL и вызывающего приложения.
Разброс очень большой - Google

Поэтому рекомендую по возможности сначала отладить логику Вашей задачи в отдельном приложении (exe), а уже затем переносить ее в библиотеку (dll) и реализовывать в виде прикладной задачи ГИС Оператор.
Если, конечно, это возможно.


Цитата
Евгений написал:
Мне удалось получить доступ к созданию объектов на новой карте через mapOpenMap. Как-то не сразу дошло до меня его использовать.
Это, скорее всего, не решение задачи. Заменив функцию, Вы изменили слегка логику работы программы, значит перераспределили память по-другому. Если ошибка по памяти есть, она вылезет в другом месте.


Ну и как догадка - а Вы после того, как получаете HSITE методом mapCreateAndAppendSite, перед тем, как его использовать, случайно не закрываете основную карту?
Страницы: 1
Читают тему (гостей: 1)



© КБ Панорама, 1991-2024

Регистрируясь или авторизуясь на форуме, Вы соглашаетесь с Политикой конфиденциальности