Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Как возвратить строку из dll без ShareMem? [D7, 95/98, ME]


Страницы:   1 2

AMW ©   (2007-03-04 21:34:00) 

Мне нужно возвратить строку из процедуры/функции dll, как это сделать не подключая ShareMem?
Заранее спасибо!


SlymRO   (2007-03-12 10:34:00) [1]

begin...end ©   (09.03.07 13:19) [33]
Из правила всегда есть исключение. В данном контексте строковая константа... Но при динамической загрузке/выгрузке dll могут возникнуть грабли с указателем на константу в адресах выгруженной dll :):
var r:integer;
begin
Lib:=LoadLibrary('lib.dll');
Int := GetProcAddress(Lib, PChar(ProcName));
r:=Int;
FreeLibrary(Lib);//Имею право выгрузить...
Value := Copy(String(Pointer(r)^), 0,Length(String(Pointer(r)^)));
end;


ни её служебные поля не изменятся
тогда и нужно ими пользоваться во избежания [26]:
var
 r:integer;
 s:string;
begin
 r:=PrgName;
 SetString(s,PChar(r),PInteger(r-4)^);
 Caption:=s;
end;


begin...end   (2007-03-09 13:19:00) [2]

> SlymRO ©   (09.03.07 12:32) [32]

> Для меня string прежде всего структура с валидными полями
> refcount,size

Пусть так. У строковой константы тоже есть поля счётчика ссылок (правда, этот счётчик для неё всегда равен -1) и размера. Но это ничего не меняет. После выхода из подпрограммы ни тело строковой константы, ни её служебные поля не изменятся.


SlymRO   (2007-03-09 12:32:00) [3]

begin...end ©   (07.03.07 20:52) [31]
Нет, здесь он не прав

Для меня string прежде всего структура с валидными полями refcount,size а уж потом "Тело строки"... а память, она и в африке память пока никто не затрет она действительна...
а операция String(PChar(PrgName)) не приведение типа! а восстановление типа, с пересчетом поля size по символу #0


begin...end   (2007-03-07 20:52:00) [4]

> GrayFace ©   (07.03.07 20:40) [30]
> SlymRO прав.

В чём? В том, что "После выхода из функции string отсутствует"? Нет, здесь он не прав. Тело строки как существовало до выхода из функции, так и существует. А указатель... да, разумеется, возвращается не указатель на тело (вопреки тому, что утверждается в [23]: "остается указатель на память - строковой константы"), а адрес адреса. С этим я и не спорил, вообще-то.


GrayFace   (2007-03-07 20:40:00) [5]

begin...end ©   (07.03.07 16:54) [27]
> SlymRO ©   (07.03.07 10:04) [23]
> остается указатель на память - строковой константы

Остаётся. Причём остаётся действительный указатель.


Во втором случае возвращается указатель на нечто в стеке, SlymRO прав. А первый - относительная редкость.


Amoeba   (2007-03-07 18:48:00) [6]

Как альтернатива ShareMem - FastMM ( http://sourceforge.net/projects/fastmm). Тоже самое, но без DLL.


Loginov Dmitry   (2007-03-07 18:40:00) [7]

> Ээ... Зачэм обижаещь?


Кого это я обижал?


begin...end   (2007-03-07 16:54:00) [8]

> SlymRO ©   (07.03.07 10:04) [23]
> остается указатель на память - строковой константы

Остаётся. Причём остаётся действительный указатель.

> SlymRO ©   (07.03.07 12:56) [25]
> Одын фиг в LStrClr попадает...

Попадает. Но память, естественно, не освобождается.

> SlymRO ©   (07.03.07 12:59) [26]

И чё?


SlymRO   (2007-03-07 12:59:00) [9]

Loginov Dmitry ©   (07.03.07 11:04) [24]
Тады будет работать.

На те поддых:
Function PrgName: Integer; stdcall;
var s:string;
Begin
S := 'Контроль заявок'#0'Fuck';
Result := Integer(S);
end;


SlymRO   (2007-03-07 12:56:00) [10]

Loginov Dmitry ©   (07.03.07 11:04) [24]
Ты вообще бред какой-то написал

Ээ... Зачэм обижаещь? Это нэ я писаль а Alexandr Bydantcev ©   (05.03.07 11:45) [16]
Я просто S задекларировалъ
Loginov Dmitry ©   (07.03.07 11:04) [24]
Result := Integer(S);

Э таварищь нэ чэстно патсказыват... Одын фиг в LStrClr попадает...


Loginov Dmitry   (2007-03-07 11:04:00) [11]

> А это не работает:


Ты вообще бред какой-то написал. Нужно не так

Result := Integer(@S);

а так

Result := Integer(S);

Тады будет работать.


SlymRO   (2007-03-07 10:04:00) [12]

begin...end ©   (06.03.07 14:41) [22]
Потому как строковая константа

остается указатель на память - строковой константы и то смотря как сделать...
Это работает:
var s:string;
Function PrgName: Integer; stdcall;
Begin
 S := 'Контроль заявок';
 Result := Integer(@S);
end;

А это не работает:
Function PrgName: Integer; stdcall;
var s:string;
Begin
 S := 'Контроль заявок';
 Result := Integer(@S);
end;


begin...end   (2007-03-06 14:41:00) [13]

> SlymRO ©   (06.03.07 07:22) [20]

> После выхода из функции string отсутствует

В данном случае после выхода из функции string присутствует. Потому как строковая константа.


Loginov Dmitry   (2007-03-06 07:55:00) [14]

> Int := GetProcAddress(Lib, PChar(ProcName));
> Value := Copy(String(Pointer(Int)^), 0, Length(String(Pointer(Int)^)));


Гы! Мощная травка!


SlymRO   (2007-03-06 07:22:00) [15]

Alexandr Bydantcev ©   (05.03.07 12:02) [18]
Value := Copy(String(Pointer(Int)^), 0, Length(String(Pointer(Int)^)));

!Ё маё... Ацес виолатионы часто ловишь? и еще: дважды вызвал процедуру (хватило бы одного раза)
Alexandr Bydantcev ©   (05.03.07 11:45) [16]
Function PrgName: Integer; stdcall;
Begin
S := 'Контроль заявок';
Result := Integer(@S);
end;

После выхода из функции string отсутствует, остается указатель на память, которая может содержать все что угодно... в твоем случае повезло
В однопоточном проекте в 100 строчек это может работать... В большом многопоточном приложении будут возникать ацесвиолатины случайным образом, что чревато сложностями в отладке...
И поэтому именно проще все стандартизировать и не изкать в 2 тыс. строках один нерегулярный баг


Аноним   (2007-03-05 12:04:00) [16]


> SlymRO ©   (05.03.07 11:13) [11]
> Аноним   (05.03.07 10:36) [10]
> Самый простой способ: это стандартизация соглашений о вызове
> процедур и о порядке освобождения ресурсов.
> а то что WideString values are not reference-counted еще
> не выход


По твоему это более простой способ?
Отнюдь.
Может быть, он более грамотный, более правильный, но не более простой


Alexandr Bydantcev   (2007-03-05 12:02:00) [17]

2 SlymRo

Можешь не верить, но работает

Извиняюсь, не указал процесс получения

var
 Lib : THandle;

Procedure GetInfo(var Value: String; ProcName: String);

var
 Proc : TFarProc;

begin
 Int := GetProcAddress(Lib, PChar(ProcName));
 Value := Copy(String(Pointer(Int)^), 0, Length(String(Pointer(Int)^)));
end


SlymRO   (2007-03-05 11:50:00) [18]

Alexandr Bydantcev ©   (05.03.07 11:45) [16]
Integer(@S);

И что? Работает? Сам то проверял?


Alexandr Bydantcev   (2007-03-05 11:45:00) [19]

Function PrgName: Integer; stdcall;
Begin
 S := 'Контроль заявок';
 Result := Integer(@S);
end;

Exports PrgName name 'PrgName';


SlymRO   (2007-03-05 11:43:00) [20]

Leonid Troyanovsky ©   (05.03.07 11:28) [14]
Чего-то мутно

А чего мутного? По идее должнобыть EQ!, но нет...
Leonid Troyanovsky ©   (05.03.07 11:28) [14]
константы разбирать

Тоже без констант:
program Project2;

{$APPTYPE CONSOLE}

uses SysUtils;

const TestStr1='hello ';
const TestStr2='world';

function TestProc:PWidestring;
var temp:widestring;
begin
temp:=TestStr1+TestStr2;
result:=@temp;
end;

var temp1,temp2:widestring;
begin
temp1:=TestProc()^;
temp2:=TestStr1+TestStr2;
if temp1<>temp2 then
  writeln('Not EQ')
else
  writeln('EQ!');
end.


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо