Вниз
Скачать: CL | DM;

из 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 из одной кучи будут и по умолчанию.



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

Скачать: CL | DM;



Память: 0.55 MB
Время: 0.036 c
15-1162075852
Petr V.Abramov
2006-10-29 02:50
2006.11.19
и че народ на стеки потянуло последние дни...


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


3-1158518226
PHPDeveloper
2006-09-17 22:37
2006.11.19
paradox без BDE


2-1162293414
Alex_C
2006-10-31 14:16
2006.11.19
Какое событие происходит при изменении текста в мемо?


6-1151406325
alex_pv1
2006-06-27 15:05
2006.11.19
Установить IP




   Наверх