Форум: "Начинающим";
Текущий архив: 2007.04.01;
Скачать: [xml.tar.bz2];
ВнизКак возвратить строку из dll без ShareMem? Найти похожие ветки
← →
AMW (2007-03-04 21:34) [0]Мне нужно возвратить строку из процедуры/функции dll, как это сделать не подключая ShareMem?
Заранее спасибо!
← →
Palladin © (2007-03-04 21:53) [1]использовать PChar
← →
Loginov Dmitry © (2007-03-04 23:27) [2]Очень просто. Резервируешь заранее место под строку необходимого размера, затем вызваешь функцию из DLL и передаешь в нее адрес строки в виде PChar.
← →
AMW (2007-03-05 00:17) [3]Написал так:
// DLL
library Project2;
uses
SysUtils, Windows;
procedure TestProc(var buf: PChar); stdcall
var
s: string;
begin
s := "Test";
Move(s[1],buf^,Length(s));
end;
exports
TestProc Name "TestProc";
end.
// В программе:
procedure TestProc(var buf: PChar); stdcall; external "Project2.dll";
procedure TForm1.Button2Click(Sender: TObject);
var
buf: PChar;
begin
GetMem(buf,10);
TestProc(buf);
Edit1.Text := buf;
FreeMem(buf);
end;
В Edit записывается строка "Testð<". Что это за символы "ð<"?
← →
TRUNK © (2007-03-05 00:41) [4]procedure TestProc(buf: PChar); stdcall
var
s: string;
begin
s := "Test";
Move(s[1],buf,Length(s));
end;
procedure TForm1.Button2Click(Sender: TObject);
var
buf: array[0..9] of Char;
begin
FillChar(buf,SizeOf(buf),0);
TestProc(buf);
Edit1.Text := buf;
end;
← →
TRUNK © (2007-03-05 00:43) [5]> TRUNK © [4]
Ошибочка вышла :(
TestProc(@buf);
← →
TRUNK © (2007-03-05 00:49) [6]> TRUNK © [4]
Ещё одна ошибка :((
Move(s[1],buf^,Length(s));
или
MoveMemory(@s[1],buf,Length(s));
← →
Loginov Dmitry © (2007-03-05 07:54) [7]
procedure TestProc(buf: PChar); stdcall
var
s: string;
begin
s := "Test";
MoveMemory(Pointer(s), buf, Length(s));
buf[Length(s)] := #0;
end;
← →
begin...end © (2007-03-05 08:52) [8]
procedure TestProc(var buf: PChar); stdcall;
var
s: string;
begin
s := "Test";
Move(s[1], buf^, Length(s) + 1)
end
← →
SlymRO © (2007-03-05 09:54) [9]аля WinApi
function TestProc(buf:PChar;bufSize:integer):integer; stdcall;
var s: string;
begin
s := "Test";
result:=Length(s)+1;
if bufSize=0 then exit;
if result>bufSize then
result:=bufSize;
StrLCopy(buf,PChar(s),result-1);
end;
← →
Аноним (2007-03-05 10:36) [10]Самый простой способ (если не хватает опыта разрулиться с указателями и выделениями памяти) - вместо String использовать WideString
← →
SlymRO © (2007-03-05 11:13) [11]Аноним (05.03.07 10:36) [10]
Самый простой способ: это стандартизация соглашений о вызове процедур и о порядке освобождения ресурсов.
а то чтоWideString values are not reference-counted
еще не выход
← →
Leonid Troyanovsky © (2007-03-05 11:22) [12]
> SlymRO © (05.03.07 11:13) [11]
> а то что WideString values are not reference-counted еще не выход
Там дело в том, что оные строки распределяются не
дельфийским менеджером, а, скажем так, через COM.
--
Regards, LVT.
← →
SlymRO © (2007-03-05 11:22) [13]пример панацеи widestring:
program Project2;
{$APPTYPE CONSOLE}
uses SysUtils;
const TestStr="hello world";
function TestProc:PWidestring;
var temp:widestring;
begin
temp:=TestStr;
result:=@temp;
end;
var temp:widestring;
begin
temp:=TestProc()^;
if temp<>teststr then
writeln("Not EQ")
else
writeln("EQ!");
end.
← →
Leonid Troyanovsky © (2007-03-05 11:28) [14]
> SlymRO © (05.03.07 11:22) [13]
> пример панацеи widestring:
Чего-то мутно.
Да и не должны мы в subject константы разбирать.
--
Regards, LVT.
← →
SlymRO © (2007-03-05 11:43) [15]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.
← →
Alexandr Bydantcev © (2007-03-05 11:45) [16]Function PrgName: Integer; stdcall;
Begin
S := "Контроль заявок";
Result := Integer(@S);
end;
Exports PrgName name "PrgName";
← →
SlymRO © (2007-03-05 11:50) [17]Alexandr Bydantcev © (05.03.07 11:45) [16]
Integer(@S);
И что? Работает? Сам то проверял?
← →
Alexandr Bydantcev © (2007-03-05 12:02) [18]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
← →
Аноним (2007-03-05 12:04) [19]
> SlymRO © (05.03.07 11:13) [11]
> Аноним (05.03.07 10:36) [10]
> Самый простой способ: это стандартизация соглашений о вызове
> процедур и о порядке освобождения ресурсов.
> а то что WideString values are not reference-counted еще
> не выход
По твоему это более простой способ?
Отнюдь.
Может быть, он более грамотный, более правильный, но не более простой
← →
SlymRO © (2007-03-06 07:22) [20]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 тыс. строках один нерегулярный баг
← →
Loginov Dmitry © (2007-03-06 07:55) [21]> Int := GetProcAddress(Lib, PChar(ProcName));
> Value := Copy(String(Pointer(Int)^), 0, Length(String(Pointer(Int)^)));
Гы! Мощная травка!
← →
begin...end © (2007-03-06 14:41) [22]> SlymRO © (06.03.07 07:22) [20]
> После выхода из функции string отсутствует
В данном случае после выхода из функции string присутствует. Потому как строковая константа.
← →
SlymRO © (2007-03-07 10:04) [23]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;
← →
Loginov Dmitry © (2007-03-07 11:04) [24]> А это не работает:
Ты вообще бред какой-то написал. Нужно не такResult := Integer(@S);
а такResult := Integer(S);
Тады будет работать.
← →
SlymRO © (2007-03-07 12:56) [25]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 попадает...
← →
SlymRO © (2007-03-07 12:59) [26]Loginov Dmitry © (07.03.07 11:04) [24]
Тады будет работать.
На те поддых:Function PrgName: Integer; stdcall;
var s:string;
Begin
S := "Контроль заявок"#0"Fuck";
Result := Integer(S);
end;
← →
begin...end © (2007-03-07 16:54) [27]> SlymRO © (07.03.07 10:04) [23]
> остается указатель на память - строковой константы
Остаётся. Причём остаётся действительный указатель.
> SlymRO © (07.03.07 12:56) [25]
> Одын фиг в LStrClr попадает...
Попадает. Но память, естественно, не освобождается.
> SlymRO © (07.03.07 12:59) [26]
И чё?
← →
Loginov Dmitry © (2007-03-07 18:40) [28]> Ээ... Зачэм обижаещь?
Кого это я обижал?
← →
Amoeba © (2007-03-07 18:48) [29]Как альтернатива ShareMem - FastMM (http://sourceforge.net/projects/fastmm). Тоже самое, но без DLL.
← →
GrayFace © (2007-03-07 20:40) [30]begin...end © (07.03.07 16:54) [27]
> SlymRO © (07.03.07 10:04) [23]
> остается указатель на память - строковой константы
Остаётся. Причём остаётся действительный указатель.
Во втором случае возвращается указатель на нечто в стеке, SlymRO прав. А первый - относительная редкость.
← →
begin...end © (2007-03-07 20:52) [31]> GrayFace © (07.03.07 20:40) [30]
> SlymRO прав.
В чём? В том, что "После выхода из функции string отсутствует"? Нет, здесь он не прав. Тело строки как существовало до выхода из функции, так и существует. А указатель... да, разумеется, возвращается не указатель на тело (вопреки тому, что утверждается в [23]: "остается указатель на память - строковой константы"), а адрес адреса. С этим я и не спорил, вообще-то.
← →
SlymRO © (2007-03-09 12:32) [32]begin...end © (07.03.07 20:52) [31]
Нет, здесь он не прав
Для меня string прежде всего структура с валидными полями refcount,size а уж потом "Тело строки"... а память, она и в африке память пока никто не затрет она действительна...
а операция String(PChar(PrgName)) не приведение типа! а восстановление типа, с пересчетом поля size по символу #0
← →
begin...end © (2007-03-09 13:19) [33]> SlymRO © (09.03.07 12:32) [32]
> Для меня string прежде всего структура с валидными полями
> refcount,size
Пусть так. У строковой константы тоже есть поля счётчика ссылок (правда, этот счётчик для неё всегда равен -1) и размера. Но это ничего не меняет. После выхода из подпрограммы ни тело строковой константы, ни её служебные поля не изменятся.
← →
SlymRO © (2007-03-12 10:34) [34]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;
Страницы: 1 вся ветка
Форум: "Начинающим";
Текущий архив: 2007.04.01;
Скачать: [xml.tar.bz2];
Память: 0.53 MB
Время: 0.042 c