Форум: "Начинающим";
Текущий архив: 2012.04.29;
Скачать: [xml.tar.bz2];
Вниз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
-------- DllProcedure 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;
-------------- VBPublic 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;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.003 c