![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
dll без менеджера памяти для передачи строк
Gu © (2012-01-05 11:18:00)Если у кого есть время, проверьте плз, небольшую программку:
Дано:
1. dll, в ней юнит
unit DllUnit; interface
uses windows, sysutils;
Procedure GuPrcA(var p:PAnsiChar;const l:integer); StdCall;
Procedure GuPrcW(var p:PWideChar;const l:integer); StdCall;
Exports GuPrcA,GuPrcW;
implementation
procedure GuMes(s:string);
begin
MessageBox(0,pchar(s),'From dll',mb_iconinformation);
end;
Procedure GuPrcW(var p:PWideChar;const l:integer); // wide
var s:widestring;
begin
if (p=nil)or(l<1) then begin p:=nil;exit;end;
SetLength(s,trunc(l/sizeof(widechar)));Move(p^,Pointer(s)^,l);
gumes('l: '+inttostr(l)+', nl: '+inttostr(length(s))+#10+'-'+s+'-');
s:=widestring(Uppercase(s));Move(Pointer(s)^,p^,l);
end;
Procedure GuPrcA(var p:Pansichar;const l:integer); // ansi
var s:ansistring;
begin
if (p=nil)or(l<1) then begin p:=nil;exit;end;
SetLength(s,l);Move(p^,Pointer(s)^,l);
gumes('l: '+inttostr(l)+', nl: '+inttostr(length(s))+#10+'-'+s+'-');
s:=ansistring(AnsiUppercase(s));Move(Pointer(s)^,p^,l);
end;
Initialization
ReportMemoryLeaksOnShutdown:=true;
end.
2. Прога, на окне мемо и 2 кнопки
...
implementation
{$R *.dfm}
Procedure GuPrcA(var p:PansiChar;const l:cardinal); StdCall; external 'mydll.dll' name 'GuPrcA';
Procedure GuPrcW(var p:PwideChar;const l:cardinal); StdCall; external 'mydll.dll' name 'GuPrcW';
procedure TForm1.Button6Click(Sender: TObject);
var p:pwidechar;c:cardinal;s:widestring;
begin
s:=widestring(memo1.Text);
c:=length(s)*sizeof(widechar);
p:=allocmem(c);
Move(Pointer(s)^,p^,c);
GuPrcW(p,c);
s:='';setlength(s,trunc(c/sizeof(widechar)));
Move(p^,Pointer(s)^,c);
Freemem(p,c);
memo1.Text:='='+s+'= l:'+inttostr(c);
end;
procedure TForm1.Button7Click(Sender: TObject);
var p:pansichar;c:cardinal;s:ansistring;
begin
s:=ansistring(memo1.text);
c:=length(s);
p:=allocmem(c);
Move(Pointer(s)^,p^,c);
GuPrcA(p,c);
s:='';setlength(s,c);
Move(p^,Pointer(s)^,c);
Freemem(p,c);
memo1.Text:='='+s+'= l:'+inttostr(c);
end;
Initialization
ReportMemoryLeaksOnShutdown:=true;
end.
исходник обоих (много зеркал): http://www.multiupload.com/WSZKF8IGP1
при нажатии на кнопки происходит передача в длл строки (ansi или wide), отображение ее в msgbox dll, обработка ее там (простой uppercase) и возврат в программу. Менеджер памяти не используется. И в проге и в dll включены ReportMemoryLeaksOnShutdown (отображение событий о потерях памяти), которые оба молчат, т.е. вроде бы все работает и длины строк тоже везде совпадают.
Что надо:
1. Посмотреть, нет ли там ошибок
2. Нельзя ли что-то оптимизировать или может есть какой способ лучше
Спасибо
Gu (2012-01-05 16:18:00) [1]ага заработало, заменил на ByRef
все всем спасибо
RWolf (2012-01-05 16:13:00) [2]
> Gu (05.01.12 16:12) [20]
> не вроде все верно, byVal должно быть. Как тогда быть с
> pchar?
я уже написал в [10].
DVM (2012-01-05 16:12:00) [3]
> Gu (05.01.12 16:10) [19]
> а как там по другому отметить, что это VAR перемення? т.
> е. отправить-получить?
http://msdn.microsoft.com/ru-ru/library/ddck1z30.aspx
RWolf (2012-01-05 16:12:00) [4]
> Gu (05.01.12 16:10) [19]
здесь у ключевого слова var другой смысл.
это значит, что: 1) при вызове на стек будет положен адрес переменной, а не она сама, 2) по этому адресу можно записывать данные.
Gu (2012-01-05 16:12:00) [5]не вроде все верно, byVal должно быть. Как тогда быть с pchar?
Gu (2012-01-05 16:10:00) [6]
> RWolf © (05.01.12 16:05) [17]
а как там по другому отметить, что это VAR перемення? т.е. отправить-получить?
Gu (2012-01-05 16:08:00) [7]String: Содержит последовательности 16-битовых (2-байтовых) кодовых точек без знака со значениями в диапазоне от 0 до 65535.
Каждая кодовая точка, или код знака, представляет один символ Юникода.
Строка может содержать от нуля до приблизительно двух миллиардов (2^31) знаков Юникода.
RWolf (2012-01-05 16:05:00) [8]
> Gu (05.01.12 15:52) [14]
типы параметров не согласованы.
ByVal — значит, в стек пойдёт указатель на 1-й символ строки.
А GuPrcWSA ожидает, что там будет указатель на указатель.
ну, и с stdcall надо бы прояснить — не знаю, как его писать в бейсике.
Gu (2012-01-05 16:05:00) [9]wide по умолчанию вроде. потому там при Public Declare Auto Sub можно вместо Auto написать Unicode (тоже не работает)
DVM (2012-01-05 16:01:00) [10]А в VB строки Wide или Ansi?
Gu (2012-01-05 15:52:00) [11]что-то както VB (VS 2010) криво работает при pchar
-------- Dll
Procedure GuPrcWSA(var s:pchar;const L:integer);
var n:string;
begin
GuMes(string(s)+' '+inttostr(l));
SetString(n,s,l);
n:=uppercase(n);
Move(Pointer(n)^,s^,l);
end;
-------------- VB
Public Declare Auto Sub GuPrcA Lib "c:\mydll.dll" Alias "GuPrcWSA" (ByVal ZZ As String, LL As Integer)
Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
Dim ZZ As String
Dim mLL As Integer
ZZ = "mama мылa mila ramu"
mLL = Len(ZZ)
GuPrcA(ZZ, mLL)
Label1.Text = ZZ
End Sub
запускается через раз, в сообщении строку не показывет, показывает только размер - 19 и обратно строку не передает. Кто VB знает, подскажите может там че не так пишу?
DVM (2012-01-05 15:31:00) [12]
> всё остальное, включая Ansi<->Unicode, преобразуется неявно.
но возможно с потерей данных о чем компилятор сообщит в предупреждении
RWolf (2012-01-05 15:18:00) [13]
> т.е. ещераз - GuPrcW подходит?
я про параметры, а не про функцию.
не надо никаких преобразований, PChar совместим со string без преобразования, всё остальное, включая Ansi<->Unicode, преобразуется неявно.
в [5] всё это уже написано.
Gu (2012-01-05 15:00:00) [14]т.е. ещераз - GuPrcW подходит?
p.s. pchar теперь = pwidechar (Xe)
те, значит все правильно:
1. в дельфи (manager памяти не юзаем)
преобразуем строку(string(unicodestring),ansistring,widestring) в pwidechar
отправляем в длл ее и ее размер
преобразуем в widestring
делаем операции с ней
преобразуем обратно в pwidechar
отпрвляем в программу ее и ее размер
в проге получаем pwidechar и преобразуем в нужную строку(string(unicodestring),ansistring,widestring)
2. в C\Vb
передаем строку и размер
...
получаем строку и размер
все так?
и что там про
> Вайд-строки (в отличие от паскалевских) можно передавать
> прямо как есть, без всяких менеджеров памяти
?
Т.е. можно
Procedure GuPrcWW(var s:widestring;L:integer);
begin
GuMes(s);
s:=widestring(uppercase(s));
end;
? это будет работать корректно для C\Vb\Delphi Xe (без манагера памяти) без потерь и гимора? Тогда и длинна в принципе не нужна (L)?
RWolf (2012-01-05 12:53:00) [15]proc GuPrcW(p:PChar; len:integer); для этого вполне подходит.
Gu (2012-01-05 12:26:00) [16]
> Вайд-строки (в отличие от паскалевских) можно передавать
> прямо как есть, без всяких менеджеров памяти.
а можно по подробнее про это?
+ а анси?
> суть в том, что, незачем выделять память вручную и перекладывать
> строки из одной в другую.
на сколько я понял, строки передавать без манагеров нельзя, потому передаю через указатели. или не так?
задача какая: передать строку (анси или виде полноценную), обработать ее и вернуть назад: 1. без манагера памяти 2. совместимо должно быть желательно с Delphi, C++\C# и Vb
RWolf (2012-01-05 12:07:00) [17]ну ок, сохраним длину строки в параметрах, не принципиально.
суть в том, что, незачем выделять память вручную и перекладывать строки из одной в другую.
_Юрий (2012-01-05 12:07:00) [18]
> Gu (05.01.12 12:02) [6]
> не не, необходимо в dll получить полноценную строку (особено
> wide)
Вайд-строки (в отличие от паскалевских) можно передавать прямо как есть, без всяких менеджеров памяти.
Gu (2012-01-05 12:02:00) [19]не не, необходимо в dll получить полноценную строку (особено wide), обработать ее (uppercase тут только для примера) и передать назад. там может быть и кодировка другая и тп - короче массив 2хбайтовых символов, где могут встречаться #0
RWolf (2012-01-05 11:57:00) [20]
> без выделений памяти под p будут потери памяти.
не будет, временем жизни строк (читай: выделением/освобождением памяти) автоматически управляет менеджер памяти.
> напишите пример, как лучше
как-то так:
Procedure GuPrcW(p:PChar); // wide
var s:string;
begin
if p=nil then exit;
gumes('l: '+inttostr(l)+', nl: '+inttostr(length(p))+#10+'-'+p+'-');
AnsiStrUpper(p);
end;
...
procedure TForm1.Button6Click(Sender: TObject);
var s:string;
begin
s:=memo1.Text;
if s<>'' then
GuPrcW(s[1]);
memo1.Text:='='+s+'= l:'+inttostr(c);
end;
предполагается, что передаваемые строки не содержат нулевых символов.