Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 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]

Это у меня глючит в голове или в компе
В dll

procedure solve (var result_ : string); stdcall;

в exe

procedure 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 теряет указатель на строку, т.к. "считает" что о ней "позаботились" в другом месте.

Передача строки через приведение, в таком виде корректна только для передачи "внутрь".
APP
var tempStr: string;
begin
   temStr:= obj.AsString;//явное создание временной строки
   solve(PChar(TempStr));//временная строка существует до выхода из процедуры
end;//временная строка уничтожена
DLL
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
1-1160182107
Doma
2006-10-07 04:48
2006.11.19
Как задать порядок присвоения св-в компоненты при создании?


2-1162559308
проходил мимо решил заглянуть
2006-11-03 16:08
2006.11.19
StringGrid


3-1158320321
Neo Trinitron
2006-09-15 15:38
2006.11.19
Громаднейшие запросы SQL


1-1160567344
YOjik
2006-10-11 15:49
2006.11.19
Несрабатывает передача параметра с 1-го раза , почему?


15-1161935751
Rule
2006-10-27 11:55
2006.11.19
Разбирается ли кто в синтезаторах ... не могу выбрать между двух





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский