OberonCore
https://forum.oberoncore.ru/

Из WinApi.PtrSTR получить массив символов
https://forum.oberoncore.ru/viewtopic.php?f=2&t=3190
Страница 1 из 1

Автор:  Виталий [ Воскресенье, 23 Январь, 2011 16:41 ]
Заголовок сообщения:  Из WinApi.PtrSTR получить массив символов

Доброго всем.
подскажите как мне из переменной WinApi.PtrSTR получить массив символов.
Например чтоб вывести в StdLog текст, который вернула WinAPI функция.

Автор:  Александр Ильин [ Воскресенье, 23 Январь, 2011 16:52 ]
Заголовок сообщения:  Re: Из WinApi.PtrSTR получить массив символов

Виталий писал(а):
подскажите как мне из переменной WinApi.PtrSTR получить массив символов.
Откуда взялся указатель? Какая функция вернула?
Обычно WinApi записывает данные по переданному ей указателю, а не возвращает указатель. Как потом память-то освобождать?

Автор:  Пётр Кушнир [ Воскресенье, 23 Январь, 2011 16:56 ]
Заголовок сообщения:  Re: Из WinApi.PtrSTR получить массив символов

Код:
TYPE
      Str* = POINTER TO ARRAY [untagged] OF SHORTCHAR;
                            ShortString* = POINTER TO ARRAY OF SHORTCHAR;

   PROCEDURE StrToShortChars* (str: Str): POINTER TO ARRAY OF SHORTCHAR;
      VAR x: ShortString; i: INTEGER;
   BEGIN
      IF (str # NIL) THEN
         NEW(x, LEN(str$)+1);
         FOR i := 0 TO LEN(str$)-1 DO x[i]:=str[i] END;
         RETURN x
      ELSE
         RETURN NIL
      END
   END StrToShortChars;



вместо str скармливаем указатель на строку. для юникода соответсвтенно SHORTCHAR заменить на CHAR

Автор:  Виталий [ Воскресенье, 23 Январь, 2011 18:11 ]
Заголовок сообщения:  Re: Из WinApi.PtrSTR получить массив символов

Значит ситуация такая: Изучаю работу ББ с Виндой. Нужно вызывать ДЛЛки написанные в Си. Делфи и т.д.
Пока моделирую ситуацию, чтоб понять как и чего.

Допустим есть ДЛЛ
Код:
library Project1;

uses    sharemem,
  SysUtils,
  windows,
  Classes;

{$R *.res}
 {$o-}
 procedure ir(var buffer:pchar);
 var s:string;
 begin
  buffer:='1234';
 end;

 exports ir;
begin
end.


Местные подсказали описать модуль импорта, что я и сделал
Код:
MODULE Dll["c:\temp\Project1.dll"];
IMPORT SYSTEM,WinApi;

TYPE   
   PROCEDURE GetBuffer* ["ir"] (VAR lpszAgent:WinApi.PtrSTR);
END Dll.

Тут все нормально.

Теперь юзаю функу ДЛЛки:
Код:
MODULE m;
IMPORT Dll,WinApi,StdLog,ComTools;

PROCEDURE a*;
VAR s:WinApi.PtrSTR;i:INTEGER;
    c:SHORTCHAR;
BEGIN
 StdLog.Clear;
 s:=ComTools.NewEmptySString(6);
 Dll.GetBuffer(s);
 i:=WinApi.GetLastError();
 IF i#0 THEN
     StdLog.String('Ошибка № ');StdLog.Int(i);StdLog.Ln;
 ELSE
  StdLog.Int(LEN(s$));StdLog.Ln;
  FOR i:=0 TO LEN(s$)-1 DO
   c:=s[i];
   StdLog.Char(c);
  END;
 END;
 ComTools.FreeSString(s);
END a;

END m.


Тут тоже норм, спасибо Петру.

Вопрос только в том верно ли я освобождаю память через ComTools.FreeSString(s); ибо на ней выпадает ошибка
Цитата:
illegal memory read

Хотя читается строка из буфера, скормленного ДЛЛке нормально

Некоторые функции примерно такой спецификации
Код:
BOOL ReadFile(
  __in   HANDLE hFile,
  __out  LPVOID lpBuffer,
  __in   DWORD dwNumberOfBytesToRead,
  __out  LPDWORD lpdwNumberOfBytesRead
);

Которые мне придется юзать (Это из самописной ДЛЛ) выдают ошибку
Цитата:
ERROR_INVALID_PARAMETER
87 (0x57)


Поэтому я и хочу научиться на примерах, пока на своих, а потом дальше в лес.

Описываю я ее в модуле так:
Код:
   PROCEDURE Read* ["ReadFile"](
     hFile:WinApi.PtrVoid;OUT lpBuffer:WinApi.PtrSTR;dwNumberOfBytesToRead:LONGINT;OUT lpdwNumberOfBytesRead:LONGINT
   ):BOOLEAN;

И вызываю примерно так как показал в своем примере, передавая туда переменку s:WinApi.PtrSTR, для которой была зарезервирована память через ComTools.NewEmptySString
Вот мне и интересно что это может быть. Где я напортачил...

Автор:  Илья Ермаков [ Воскресенье, 23 Январь, 2011 18:32 ]
Заголовок сообщения:  Re: Из WinApi.PtrSTR получить массив символов

Смотрите. Pchar - это уже указатель. А у Вас ещё и VAR Pchar. Т.е. Ваша DLL-ная функция возвращает через VAR-параметр указатель на строку.

Что и происходит. DLL-ке наплевать на Вами выделенную строку, она просто перетирает параметр указателем на строковую константу Дельфы. И освобождать в конце процедуры ББ Вы уже пытаетесь объект, находящийся в юрисдикции Дельфы.

Автор:  Виталий [ Понедельник, 24 Январь, 2011 19:38 ]
Заголовок сообщения:  Re: Из WinApi.PtrSTR получить массив символов

Хм... Так, ладно. Еще такой вариант
Код:
MODULE Dll["c:\temp\Project1.dll"];
IMPORT SYSTEM,WinApi;

TYPE   
   PROCEDURE GetBuffer* ["ir"] (buf:POINTER TO ARRAY OF SHORTCHAR);
END Dll.

И вызов:
Код:
MODULE m;
IMPORT SYSTEM,Dll,WinApi,StdLog;

PROCEDURE a*;
VAR i:INTEGER;
    buf:POINTER TO ARRAY OF SHORTCHAR;
BEGIN
 StdLog.Clear;
 NEW(buf,10);
 Dll.GetBuffer2(buf);
 i:=WinApi.GetLastError();
 IF i#0 THEN
     StdLog.String('Error ');StdLog.Int(i);StdLog.Ln;
 ELSE
  StdLog.String('String is = ');
  StdLog.String(buf$);
 END;
END a;

END m.


Выдает пустую строку, да еще и ББ потом закрывается сам собой.

Что в этом случае не так? Вроде как я передаю адрес, по которому зарезервирована память

Автор:  Geniepro [ Понедельник, 24 Январь, 2011 19:44 ]
Заголовок сообщения:  Re: Из WinApi.PtrSTR получить массив символов

С дельфийскими/си++билдеровскими DLL'ками могут быть заморочки -- они нестандартны для винды, информацию о типах содержат, вероятно и свой счётчик ссылок для строк...
Как-то тоже возился с ними -- кучу неприятных ощущений испытал.
Как тут Илья Ермаков упоминал, неприятности могут быть с теми же строками.

Автор:  Александр Шостак [ Понедельник, 24 Январь, 2011 20:13 ]
Заголовок сообщения:  Re: Из WinApi.PtrSTR получить массив символов

В делфийском модуле должна быть функция, возвращающая pchar.
GetMem/FreeMem/NEW/Dispose/String нельзя использовать.

RESULT:='1234';

А в Обероне скопируйте переданную строку в массив символов.
Если вдруг нужно передать переменную типа string из делфи в оберон, то сделайте её глобальной, возвращайте pchar(s).

Страница 1 из 1 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/