На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! ПРАВИЛА РАЗДЕЛА · FAQ раздела Delphi · Книги по Delphi
Пожалуйста, выделяйте текст программы тегом [сode=pas] ... [/сode]. Для этого используйте кнопку [code=pas] в форме ответа или комбобокс, если нужно вставить код на языке, отличном от Дельфи/Паскаля.
Следующие вопросы задаются очень часто, подробно разобраны в FAQ и, поэтому, будут безжалостно удаляться:
1. Преобразовать переменную типа String в тип PChar (PAnsiChar)
2. Как "свернуть" программу в трей.
3. Как "скрыться" от Ctrl + Alt + Del (заблокировать их и т.п.)
4. Как прочитать список файлов, поддиректорий в директории?
5. Как запустить программу/файл?
... (продолжение следует) ...

Вопросы, подробно описанные во встроенной справочной системе Delphi, не несут полезной тематической нагрузки, поэтому будут удаляться.
Запрещается создавать темы с просьбой выполнить какую-то работу за автора темы. Форум является средством общения и общего поиска решения. Вашу работу за Вас никто выполнять не будет.


Внимание
Попытки открытия обсуждений реализации вредоносного ПО, включая различные интерпретации спам-ботов, наказывается предупреждением на 30 дней.
Повторная попытка - 60 дней. Последующие попытки бан.
Мат в разделе - бан на три месяца...
Модераторы: jack128, D[u]fa, Shaggy, Rouse_
  
> Проблема при конвертировании PChar в Str , программа "вылетает"
    Есть функция в DLL, описанная в моей программе как
    ExpandedWrap disabled
      var
        ShareInfo: function(const WhatInfo: Cardinal): PChar;

    DLL грузится динамически, функция ShareInfo() в DLL находится корректно (GetProcAddress() возвращает <> nil). Далее, при выполнении следующий строки кода
    ExpandedWrap disabled
        Label8.Caption := StrPas(ShareInfo(1));
      <либо>
        Label8.Caption := String(ShareInfo(1));
      <либо даже так>
        Label8.Caption := ShareInfo(1);

    программа закрывается без всяких сообщений об ошибке и т.п. Это если запускать без дебаггера. Если с ним, то имеем: "Project <путь_к_exe> faulted with message 'access violation at 0x00403e4c: write of address 0x0045216b'." Опытным путем доказано, что ошибка происходит при конвертировании null-terminated строки (PAnsiChar aka PChar) в паскалевкую произвольной длины (String).

    Используем Delphi 7. Что делать и как быть?
    Сообщение отредактировано: Savant -
      Savant, покажи код функции. Но вероятней всего в функциях просто не выделяется память под PChar.
        Естественно проблемы с памятью. Щас придет Jack128 и раскритикует это дело :)
          Естественно раскритикую.
          Где память выделется под Pchar ??
          С такой сигнатурой функции
          Цитата Savant @
          function(const WhatInfo: Cardinal): PChar;


          память может выделятся только в самой функции, что не есть хорошо. Смотрим в качестве примера WinAPI. Банальный пример GetWindowText. Эта функция тоже должна вернуть строку, только вот память под эту строку выделяет не сама GetWindowText , а её клиент.

          И тебе тоже нужно сделать аналогично.

          ExpandedWrap disabled
            function ShareInfo(const WhatInfo: Cardinal; Buf: PChar; BufSize: Cardinal): Integer;

          Buf - буфер, в который фнукция вернет информацию. BufSize - размер функции. Результат функции - сколько реально байт занимает возращенная информация.
          Так же в WinAPI принято, что если в качестве параметра Buf передан nil, то функция должна вернуть необходимый размер буффера.

          И вызывать ты будешь эту функцию примерно так

          ExpandedWrap disabled
            var
              BufSize: Integer;
              Buf: Pchar;
            begin
              BufSize := ShareInfo(WhatInfo, nil, 0);
              GetMem(Buf,  BufSize);
              try
                ShareInfo(Buf, BufSize);
                ...
              finally
                FreeMem(Buf);
              end;
            end;
            jack128
            Ну допустим переделаем все как Вы предлагаете, но ведь все равно не работает :(.

            Это код в DLL:
            ExpandedWrap disabled
              function ShareInfo(const WhatInfo: Integer; Buf: PChar; const BufSize: Integer): Integer; stdcall;
              const
                info: array[1..3] of String = ('abc', 'def', 'xyz123');
              begin
                MessageBox(0, PChar(Format('%d', [WhatInfo])), 'ShareInfo() execution', 0);
                case WhatInfo of
                  1..3: begin
                    Result := Length(info[WhatInfo]) + 1; // учитываем '\0' в конце
                    if Buf <> nil then begin
                      if BufSize >= Result then begin
                        if lstrcpyn(Buf, @info[WhatInfo], Result) = nil then
                          Result := -2; // неудача записи
                      end else
                        Result := -1; // маленький буфер
                    end else begin
                      { Возвращаем нужный размер, инициализация Result парой строчек выше }
                    end;
                  end
                  else // Ошибочное значение параметра WhatInfo
                    Result := 0;
                end;
              end;


            А это вызов в программе:
            ExpandedWrap disabled
              var
                ShareInfo: function (const WhatInfo: Integer; Buf: PChar; const BufSize: Integer): Integer;
               
              var
                BufSize: Integer;
                Buf: PChar;
               
              begin
              ....
                      BufSize := ShareInfo(1, nil, 0);
                      MessageBox(0, PChar(Format('%d', [BufSize])), nil, 0);
                      GetMem(Buf, BufSize);
                      try
                        ShareInfo(1, Buf, BufSize);
                        Label8.Caption := String(Buf);
                      finally
                        FreeMem(Buf);
                      end;


            Кстати говоря, с помощью MessageBox'a в функции DLL выяснилось, что параметр WhatInfo в процессе передачи несколько искажается, в частности при первом вызове (ShareInfo(1, nil, 0)) он принимает значение 1243372 (причем при любом значении WhatInfo), а при втором (ShareInfo(1, Buf, BufSize)) - 1242508 (если WhatInfo передается как константа) или 1242512 (если как переменная). Cмахивает на адреса в памяти...

            Кто-нибудь въехал ?
              Цитата Savant @
              var
              ShareInfo: function (const WhatInfo: Integer; Buf: PChar; const BufSize: Integer): Integer;
              stdcall;
              0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
              0 пользователей:


              Рейтинг@Mail.ru
              [ Script execution time: 0,0626 ]   [ 16 queries used ]   [ Generated: 20.05.24, 04:17 GMT ]