![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Как возвратить строку из dll без ShareMem? [D7, 95/98, ME]
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.