Форум: "Начинающим";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];
Внизиз dll очень длинную строку без ShareMem Найти похожие ветки
← →
_Ламер_ (2006-10-15 19:57) [0]Народ, как из дллки передать длинную строку? shortstring не подходит, PChar передаёт около 3700 символов, а мне надо больше. exe не на делфях написана...
← →
Leonid Troyanovsky © (2006-10-15 20:16) [1]
> _Ламер_ (15.10.06 19:57)
> не подходит, PChar передаёт около 3700 символов, а мне надо
> больше. exe не на делфях написана...
Если поверишь на слово, то PChar может передать даже 4096 (!) байт.
--
Regards, LVT.
← →
_Ламер_ (2006-10-15 20:34) [2]
> Если поверишь на слово, то PChar может передать даже 4096
> (!) байт.
А мне больше надо.
← →
DrPass © (2006-10-15 20:40) [3]
> _Ламер_ (15.10.06 20:34) [2]
Тебе повезло, с этого воскресенья PChar передает до 2147483648 байт
← →
Anatoly Podgoretsky © (2006-10-15 20:42) [4]_Ламер_ (15.10.06 20:34) [2]
Не поверишь, но у тебя ошибка в программе.
← →
Anatoly Podgoretsky © (2006-10-15 20:44) [5]Кстати если не на Дельфи, то никто кроме Дельфи длинные строки не понимает. BCB не в счет. Но данный форум посвящен Дельфи, а не другим языкам программирование, так что тебе возможно на другой форум нужно?
← →
_Ламер_ (2006-10-15 22:08) [6]
> DrPass © (15.10.06 20:40) [3]
> > _Ламер_ (15.10.06 20:34) [2] Тебе повезло, с этого воскресенья
> PChar передает до 2147483648 байт
И как всё это добро перевести в string? В лоб
string := Pchar
выдаёт ошибку.
← →
Ketmar © (2006-10-15 22:22) [7]>[6] _Ламер_ 15-Oct-2006, 22:08
>string := Pchar
это, пардон, с каких пор типы присваивают? а если не типы -- код покажи. который "ошибку выдаёт". "не верю" (ц) нормально дельфи преобразовывает -- как туда, так и обратно. до 2 гб -- свободно, лишь бы мозгов хватило.
← →
_Ламер_ (2006-10-15 23:10) [8]А что код? Есть функция, которая возвращает Pchar. Есть переменная string, куда записывается результат.
Так вот
MyFunc () : Pchar;
///////
procedure solve;
var
text : string;
begin
Text := MyFunc ();
//////
end;
Работает только на небольших строках (до ~4 кБ), а дальше AV. Я уже специально {$H+} пишу - ни фига. Причём если использовать просто string и ShareMem - всё работает на ура.
← →
Ketmar © (2006-10-15 23:20) [9]небось память для PChar в DLL выделяешь? и комментарий, который Delphi вставляет при создании library -- игнорируешь, как образец буржуазного растления? так держать.
← →
_Ламер_ (2006-10-16 00:10) [10]А что, в dll нельзя писать
property AsString: string read GetAsString write SetAsString;
//и далее
function solve: pChar; stdcall;
begin
result := pChar (MyClass.AsString);
end;
?
Тогда это настоящий пинцЭт.
← →
Ketmar © (2006-10-16 00:14) [11]можно. если внимательно комментарий среды прочёл. если не прочёл -- читать. думать. вникать. медитировать над фактом того, что куч -- их две получается без ShareMem. или три. или сколько там DLL. и они (кучи) друг о друге ничего не знают.
← →
Орион © (2006-10-16 00:17) [12]если sharemem за собой носить не хочется можно взять fastsharemem, например и прочие аналоги.
← →
guav © (2006-10-16 00:41) [13]> function solve: pChar; stdcall;
> begin
> result := pChar (MyClass.AsString);
> end;
так нельзя.
рекомендую обратить внимание на то как обычно винапи функции возвращают строки. GetWindowsDirectory, GetEnvironmentVariable, например, или GetComputerName.
← →
_Ламер_ (2006-10-16 01:06) [14]Дык там и написано
To avoid using BORLNDMM.DLL, pass string information
using PChar or ShortString parameters.
Что я и пытаюсь сделать.
Пошёл по другому пути
procedure solve (var result_: pChar); stdcall;
begin
result_ := pChar (MyClass.AsString);
end;
Один хрен на больших строках спотыкается.
А если передавать по одному символу, но в цикле?
← →
_Ламер_ (2006-10-16 01:46) [15]Это у меня глючит в голове или в компе
В dllprocedure solve (var result_ : string); stdcall;
в exeprocedure solve (var dest : pChar); stdcall;
Странно, но это работает без всяких ShareMem.
Ладно, всем баиньки. Завтра будем разбираться, почему это не глючит.
← →
Ketmar © (2006-10-16 02:03) [16]>[14] _Ламер_ 16-Oct-2006, 01:06
>To avoid using BORLNDMM.DLL, pass string information
> using PChar or ShortString parameters.
читать надо вдумчиво. а не абы как. сия фраза автором ветки истолкована напрочь превратно.
>
>procedure solve (var result_: pChar); stdcall;
>begin
>result_ := pChar (MyClass.AsString);
>end;
бред.
>А если передавать по одному символу, но в цикле?
намекали: глянь, как это в WinAPI сделано.
>[15] _Ламер_ 16-Oct-2006, 01:46
>Это у меня глючит в голове или в компе
в голове.
>Странно, но это работает без всяких ShareMem.
а отчего бы ему не работать? учёт ссылок ведёт DLL, работает -- EXE. проблемы будут, когда в DLL строку освободят, а EXE об этом не узнает. автор будет долго искать ошибку, а потом напишет гневный пост типа "борланд -- отстой, даже такой простой вещи сделать не могут!"
вообще -- налицо явное незнание реализации AnsiString в Delphi. советую, всё-таки, почитать литературу. или посмотреть код, который компилятор генерирует.
← →
имя (2006-10-16 07:16) [17]Удалено модератором
← →
evvcom © (2006-10-16 08:34) [18]> [15] _Ламер_ (16.10.06 01:46)
> procedure solve
Лучше назовиprocedure Bug
:-)
← →
Пусик © (2006-10-16 10:47) [19]%$^%
Так и хочется воскликнуть - "Сколько идиотов!".
>_Ламер_
Особенность работы с DLL - это различные менеджеры памяти в DLL и основном приложении.
Поэтому проектировать DLL надо так, чтобы все перераспределения памяти оставались внутри DLL(то же касается и основного приложения).begin
result_ := pChar (MyClass.AsString);
end;
Для корректной работы такого метода у тебя есть 2 варианта:
Первый.
Выделить в DLL необходимый объем памяти и скопировать туда строку:GetMem(Result_,Length(MyClass.AsString));
Move(MyClass.AsString[1],Result_[0],Length(MyClass.AsString));
После того, как в основном приложении полученные данные будут обработаны, необходимо будет освободить выделенную память. Это нужно будет сделать опять же в DLL:procedure Resolve_(p: PChar);
begin
FreeMem(p);
end;
Это процедуре в DLL передается из основного приложения адрес выделенной перед этим памяти.
Второй:
В основном приложении заранее резервируется участок памяти.
В DLL передается адрес участка и его размер.
Процедура в DLL заполняет этот участок необходимыми данными и возвращает длину основному приложению.
Основное приложение после обработки данных освобождает память.
-----------------
В этом случае проблем при работе данными любых типов не возникнет.
Если не планируется использование DLL нигде, кроме программ, написанных на Delphi, то, как выше посоветовали, можно воспользоваться модулем FastShareMem.
← →
Сергей М. © (2006-10-16 11:00) [20]
> Пусик © (16.10.06 10:47) [19]
> Особенность работы с DLL - это различные менеджеры памяти
> в DLL и основном приложении
Не слишком ли категорично ?
Если разработчики взаимодействующих модулей договорились об использовании того или иного (единого для обоих модулей) менеджера, то никаких "особенностей" нет.
← →
Пусик © (2006-10-16 11:14) [21]
> Если разработчики взаимодействующих модулей договорились
> об использовании того или иного (единого для обоих модулей)
> менеджера, то никаких "особенностей" нет.
Это как раз и есть использование Sharemem с Borlndmm.dll или FastShareMem.
Это другая особенность, если угодно.
Или есть другие методы "договориться" кроме подобных?
← →
Сергей М. © (2006-10-16 11:34) [22]
> Пусик © (16.10.06 11:14) [21]
> есть другие методы "договориться" кроме подобных?
А как же !
Мало ли менеджеров (кроме борландовских) существует ..
Например, в составе msvcrt.
← →
han_malign © (2006-10-16 11:45) [23]
> В dll
> procedure solve (var result_ : string); stdcall;
> в exe
> procedure solve (var dest : pChar); stdcall;
> Странно, но это работает без всяких ShareMem.
- работает, какое то время, а потом будет переполнение памяти, т.к. счетчик ссылок в DLL при передаче увеличивается - в приложении игнорируется, и DLL теряет указатель на строку, т.к. "считает" что о ней "позаботились" в другом месте.
Передача строки через приведение, в таком виде корректна только для передачи "внутрь".
APPvar tempStr: string;
DLL
begin
temStr:= obj.AsString;//явное создание временной строки
solve(PChar(TempStr));//временная строка существует до выхода из процедуры
end;//временная строка уничтоженаprocedure solve(dest: PChar);
begin
globStr:= dest;//создание новой строки в DLL и копирование данных
end;
при передаче "наружу" - временная строка уничтожается по выходу из функции и приложение получает неверный указатель...
Как выход - можно кешировать строку в глобальной переменной DLL:var globCacheStr: string;
function solve: PChar;
begin
globCacheStr:= obj.AsString;//создание новой строки в DLL
Result:= PChar(globCacheStr);
end;//время жизни globCacheStr - до следущего обращения к solve
← →
Пусик © (2006-10-16 11:54) [24]
> Сергей М. © (16.10.06 11:34) [22]
> > Пусик © (16.10.06 11:14) [21]> есть другие методы "договориться"
> кроме подобных?А как же !Мало ли менеджеров (кроме борландовских)
> существует ..Например, в составе msvcrt.
Ну так в любом случае "по-умолчанию" менеджеры памяти разные. За другие языки не скажу, но в Delphi-то это так.
Так что особеннности будут, если не прикладывать усилий воизбежание этого...
← →
Сергей М. © (2006-10-16 12:20) [25]
> Пусик © (16.10.06 11:54) [24]
> Ну так в любом случае "по-умолчанию" менеджеры памяти разные
Ну так на то и существуют эти соглашения)
> в Delphi-то это так
В Делфи предусмотрен механизм перекрытия этих самых "умолчаний".
см. TMemoryManager-структуру и все связанное с ее использованием.
← →
Пусик © (2006-10-16 12:24) [26]
> В Делфи предусмотрен механизм перекрытия этих самых "умолчаний".
> см. TMemoryManager-структуру и все связанное с ее использованием.
>
Это я знаю.
Вот только это и есть дополнительные услилия.
И весьма значительные.
← →
Сергей М. © (2006-10-16 12:32) [27]
> Пусик © (16.10.06 12:24) [26]
> это и есть дополнительные усилия
А без них никак.
Но с другой стороны, затрата этих усилий с лихвой компенсируется удобствами, предоставляемыми средой Делфи при работе с данными с управляемым временем жизни.
Иными словами, после переопределения структуры TMemoryManager в соответствии с требуемым соглашением дальнейшая работа с памятью не выходит за рамки привычной.
← →
_Ламер_ (2006-10-16 21:34) [28]Пусик
огромное спасибо. Но есть ещё один вопрос. Я пошёл по второму варианту. То бишь размер поля БД мне известен, поэтому я могу выделить столько, сколько надо. А вот во FreeMem надо указывать длину или нет?
← →
Ketmar © (2006-10-16 21:40) [29]>[28] _Ламер_ 16-Oct-2006, 21:34
>во FreeMem надо указывать длину или нет?
FreeMem, f1. нет.
← →
_Ламер_ (2006-10-16 22:36) [30]И ещё один вопрос.
Как лучше урезать строку до Length? Copy(), delete(). Или быть может урезать область памяти с символами?
← →
Ketmar © (2006-10-16 22:50) [31]а без разницы. лучше Delete() -- исключительно по соображениям наглядности. %-)
← →
Loginov Dmitry © (2006-10-16 23:02) [32]_Ламер_ (16.10.06 22:36) [30]
Как лучше урезать строку до Length? Copy(), delete().
Тогда уж из соображений скорости и наглядности лучше использовать SetLength()
← →
Ketmar © (2006-10-16 23:39) [33]>[32] Loginov Dmitry(c) 16-Oct-2006, 23:02
>Тогда уж из соображений скорости и наглядности лучше
>использовать SetLength()
или так.
← →
_Ламер_ (2006-10-17 00:08) [34]Раз без разницы, буду юзать так
result := copy (pS, 0, aLength);
Всем спасибо.
Целую
← →
Ketmar © (2006-10-17 00:26) [35]>[34] _Ламер_ 17-Oct-2006, 00:08
>result := copy (pS, 0, aLength);
0??? rtfm.
← →
Германн © (2006-10-17 02:57) [36]Нет сил читать всё это.
Но размер около 4096 смутил. Было дело, было время, Digitman тут на форуме пытался найти объяснение и решение, почему в дебаггерских окнах показывается лишь до 4096 и как это превзойти. Может и тут такой же случай?
← →
Джо © (2006-10-17 03:15) [37]> [36] Германн © (17.10.06 02:57)
> Нет сил читать всё это.
> Но размер около 4096 смутил.
Размер 4096 упоминал только Palladin в первом же посте. И то — в качестве шутки :)
← →
Loginov Dmitry © (2006-10-17 07:58) [38]Германн © (17.10.06 2:57) [36]
Но размер около 4096 смутил. Было дело, было время, Digitman тут на форуме пытался найти объяснение и решение, почему в дебаггерских окнах показывается лишь до 4096 и как это превзойти
<OFFTOP>
Буквально на прошлой неделе два дня убил на работе, выясняя, почему же портится содержимое строки. Окно Evalution показывает первые 4 кБ строки нормально, а дальше - мусор, причем рандомный, и каждый раз разный. Обматерил все и вся. Оказывается причиной неработоспособности проги (а зачем еще делать дебаг) был неправильный критерий выхода из цикла while True.
А самая главная причина - лень.
Привык делать так:
with TObject.Create do...
лажа в том, что во время отладки невозможно узнать значение ни одно свойство этого объекта. И только через 2 дня дошло, что проще объявить объектную переменную, и спокойно просматривать ее свойства во время отладки.
</OFFTOP>
← →
_Ламер_ (2006-10-24 18:52) [39]Так, а если я указываю var string, то что передаётся в dll? Указатель на область памяти?
← →
guav © (2006-10-24 19:03) [40]
> [24] Пусик © (16.10.06 11:54)
AFAIR, WideString из одной кучи будут и по умолчанию.
← →
Desdechado © (2006-10-24 20:31) [41][0]
> exe не на делфях написана
меня что-то это смущает...
← →
Пусик © (2006-10-24 21:55) [42]
> Так, а если я указываю var string, то что передаётся в dll?
> Указатель на область памяти?
Передается указатель на String.
В DLL(без общего менеджера памяти) ты можешь читать и изменять область памяти, на которую указывает @Str[1] длиной Length(Str).
← →
_Ламер_ (2006-10-25 20:43) [43]Прошу прощения, но что-то я не догоняю. Что произойдёт, если я в dll этой var string присвою значение переменной, определённой в dll тоже как string. примерно как-то так
var
Str1 : string;
.....
procedure solve (var Str2 : string); stdcall;
begin
Str2 := Str1;
....
end;
Что я получу в Str2 - свой старый указатель или новый на строку Str1?
← →
Ketmar © (2006-10-25 20:59) [44]>[42] Пусик(c) 24-Oct-2006, 21:55
>изменять
да? ух, ты. век живи, век учись... а я наивно считал, что у AnsiString ещё reference counter есть. который приделали вовсе не зря.
>[43] _Ламер_ 25-Oct-2006, 20:43
>Что я получу в Str2 - свой старый указатель или новый на
>строку Str1?
ага. и AV потом. рассказать, где можно метлу купить?
← →
_Ламер_ (2006-10-30 20:02) [45]А можно по WideString вопрос? Можно, правда?
var
edLogin, edPassword : WideString;
......
procedure PostInfo (aLogin, aPassword : PWideChar; var LLength, PLength : byte); stdcall;
begin
if (aLogin = nil) or (aPassword = nil) then exit;
LLength := Length (edLogin);
Move (edLogin[1], aLogin[0], LLength);
PLength := Length (edPassword);
Move (edPassword[1], aPassword[0], PLength);
MessageBoxW (0, PWideChar (edLogin), PWideChar (edPassword), MB_OK);
MessageBoxW (0, aLogin, aPassword, MB_OK);
end;
Первый MessageBox покзывает строки правильно, второй - только их половину. Где, что не так?
← →
Leonid Troyanovsky © (2006-10-30 20:19) [46]
> _Ламер_ (30.10.06 20:02) [45]
> А можно по WideString вопрос? Можно, правда?
Это смотря чего и сколько прочитано.
Хотя, в любом случае, похоже, усваивается плохо.
Поэтому, по одному вопросу, плиз.
--
Regards, LVT.
← →
_Ламер_ (2006-10-30 22:56) [47]Почитал справку. Оказывается Length для Unicode возвращает половину длины. Интересно, почему? И почему для 1234 он возвращает 4, но копирует всего 2 символа?
← →
Leonid Troyanovsky © (2006-10-30 23:14) [48]
> _Ламер_ (30.10.06 22:56) [47]
> половину длины. Интересно, почему? И почему для 1234 он
> возвращает 4, но копирует всего 2 символа?
А, ведь, интересно читать справку?
Но, нам, пока, не очевидна связь между edLogin & aLogin.
--
Regards, LVT.
← →
DiamondShark © (2006-10-31 01:20) [49]
> А что, в dll нельзя писать
...
> result := pChar (MyClass.AsString);
не только в длл. нигде нельзя.
время валидности указателя, возвращаемого операцией PChar(<string expression>) -- область видимости <string expression>.
в приведённом случае -- это один оператор.
← →
_Ламер_ (2006-10-31 11:49) [50]Память для aLogin выделяет exe и передаёт указатель в dll.
← →
Leonid Troyanovsky © (2006-10-31 14:14) [51]
> _Ламер_ (30.10.06 22:56) [47]
> Почитал справку. Оказывается Length для Unicode возвращает
> половину длины. Интересно, почему?
Во-первых, Length возвращает число символов.
Во-вторых, юникодный символ - это 2 байта.
> И почему для 1234 он возвращает 4, но копирует всего 2 символа?
Кто "он"? Кто возвращает и кто копирует?
Показывай.
--
Regards, LVT.
← →
Leonid Troyanovsky © (2006-10-31 14:20) [52]
> _Ламер_ (31.10.06 11:49) [50]
> Память для aLogin выделяет exe и передаёт указатель в dll.
А откуда взялось edLogin?
Кста, тебе ж разрешили в dll возвращать (передавать) WideString.
Т.е., function y (x: WideString): WideString;
Только, stdcall тебе зачем?
--
Regards, LVT.
← →
_Ламер_ (2006-11-01 10:51) [53]В edLogin моя строка находится.
Ну в общем всем спасибо.
Всех целую.
Будут вопросы - обязательно загляну.
Страницы: 1 2 вся ветка
Форум: "Начинающим";
Текущий архив: 2006.11.19;
Скачать: [xml.tar.bz2];
Память: 0.6 MB
Время: 0.045 c