Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2012.04.29;
Скачать: CL | DM;

Вниз

dll без менеджера памяти для передачи строк   Найти похожие ветки 

 
Gu   (2012-01-05 11:18) [0]

Если у кого есть время, проверьте плз, небольшую программку:

Дано:
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 11:23) [1]

Delphi Xe, забыл написать


 
RWolf ©   (2012-01-05 11:25) [2]

> trunc(l/sizeof(widechar))

В паскале это пишется так: l div sizeof(widechar).

Нельзя ли что-то оптимизировать

В программе неоправданно много ручных выделений/освобождений динамической памяти. Рекомендуется уменьшить до нуля.


 
Gu   (2012-01-05 11:45) [3]

так это.. без выделений памяти под p будут потери памяти. напишите пример, как лучше


 
Dimka Maslov ©   (2012-01-05 11:56) [4]

Бред написан. Полный бред. Так делать нельзя. Тут 95% лишнего кода.


 
RWolf ©   (2012-01-05 11:57) [5]


> без выделений памяти под 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;


предполагается, что передаваемые строки не содержат нулевых символов.


 
Gu   (2012-01-05 12:02) [6]

не не, необходимо в dll получить полноценную строку (особено wide), обработать ее (uppercase тут только для примера) и передать назад. там может быть и кодировка другая и тп - короче массив 2хбайтовых символов, где могут встречаться #0


 
_Юрий   (2012-01-05 12:07) [7]


> Gu   (05.01.12 12:02) [6]


> не не, необходимо в dll получить полноценную строку (особено
> wide)


Вайд-строки (в отличие от паскалевских) можно передавать прямо как есть, без всяких менеджеров памяти.


 
RWolf ©   (2012-01-05 12:07) [8]

ну ок, сохраним длину строки в параметрах, не принципиально.
суть в том, что, незачем выделять память вручную и перекладывать строки из одной в другую.


 
Gu   (2012-01-05 12:26) [9]


> Вайд-строки (в отличие от паскалевских) можно передавать
> прямо как есть, без всяких менеджеров памяти.

а можно по подробнее про это?
+ а анси?


> суть в том, что, незачем выделять память вручную и перекладывать
> строки из одной в другую.

на сколько я понял, строки передавать без манагеров нельзя, потому передаю через указатели. или не так?
задача какая: передать строку (анси или виде полноценную), обработать ее и вернуть назад: 1. без манагера памяти 2. совместимо должно быть желательно с Delphi, C++\C# и Vb


 
RWolf ©   (2012-01-05 12:53) [10]

proc GuPrcW(p:PChar; len:integer); для этого вполне подходит.


 
Gu   (2012-01-05 15:00) [11]

т.е. ещераз - 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 15:18) [12]


> т.е. ещераз - GuPrcW подходит?

я про параметры, а не про функцию.

не надо никаких преобразований, PChar совместим со string без преобразования, всё остальное, включая Ansi<->Unicode, преобразуется неявно.
в [5] всё это уже написано.


 
DVM ©   (2012-01-05 15:31) [13]


> всё остальное, включая Ansi<->Unicode, преобразуется неявно.

но возможно с потерей данных о чем компилятор сообщит в предупреждении


 
Gu   (2012-01-05 15:52) [14]

что-то както 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 16:01) [15]

А в VB строки Wide или Ansi?


 
Gu   (2012-01-05 16:05) [16]

wide по умолчанию вроде. потому там при Public Declare Auto Sub можно вместо Auto написать Unicode (тоже не работает)


 
RWolf ©   (2012-01-05 16:05) [17]


> Gu   (05.01.12 15:52) [14]

типы параметров не согласованы.
ByVal — значит, в стек пойдёт указатель на 1-й символ строки.
А GuPrcWSA ожидает, что там будет указатель на указатель.
ну, и с stdcall надо бы прояснить — не знаю, как его писать в бейсике.


 
Gu   (2012-01-05 16:08) [18]

String: Содержит последовательности 16-битовых (2-байтовых) кодовых точек без знака со значениями в диапазоне от 0 до 65535.
Каждая кодовая точка, или код знака, представляет один символ Юникода.
Строка может содержать от нуля до приблизительно двух миллиардов (2^31) знаков Юникода.


 
Gu   (2012-01-05 16:10) [19]


> RWolf ©   (05.01.12 16:05) [17]

а как там по другому отметить, что это VAR перемення? т.е. отправить-получить?


 
Gu   (2012-01-05 16:12) [20]

не вроде все верно, byVal должно быть. Как тогда быть с pchar?


 
RWolf ©   (2012-01-05 16:12) [21]


> Gu   (05.01.12 16:10) [19]

здесь у ключевого слова var другой смысл.
это значит, что: 1) при вызове на стек будет положен адрес переменной, а не она сама, 2) по этому адресу можно записывать данные.


 
DVM ©   (2012-01-05 16:12) [22]


> Gu   (05.01.12 16:10) [19]


> а как там по другому отметить, что это VAR перемення? т.
> е. отправить-получить?

http://msdn.microsoft.com/ru-ru/library/ddck1z30.aspx


 
RWolf ©   (2012-01-05 16:13) [23]


> Gu   (05.01.12 16:12) [20]
> не вроде все верно, byVal должно быть. Как тогда быть с
> pchar?

я уже написал в [10].


 
Gu   (2012-01-05 16:18) [24]

ага заработало, заменил на ByRef
все всем спасибо



Страницы: 1 вся ветка

Текущий архив: 2012.04.29;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.008 c
2-1325371999
Gu
2012-01-01 02:53
2012.04.29
строки Xe2


2-1325588259
Валерий
2012-01-03 14:57
2012.04.29
Запретить перемещение окна зная его handle


15-1325070765
Artem
2011-12-28 15:12
2012.04.29
Транслятор стандартного паскаля в ассемблер..


15-1324586003
Германн
2011-12-23 00:33
2012.04.29
Как очистить пространство имен СОМ-портов?


2-1325596272
serhiyiv
2012-01-03 17:11
2012.04.29
Медиа кнопки + message