Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

DLL в Delphi [D7, WinXP]


Страницы:   1 2 3 4

DimOk ©   (2007-06-27 17:08:00) 

Столкнулся с такой проблемой: есть DLL в котором находятся функции для работы с PChar. Подключаю DLL динамически к основной программе, получаю адрес необходимой функции и передаю в нее параметр PChar, при отладке в основной программе указан именно тот набор символов, который пользователь вводит, но как только заходим в проект DLL и смотрим там параметр, который передавали то видим совсем другую картину (вводим 123 а получаем Ⱥ}{ÓvF), может кто знает как устранить такую проблему. Буду очень благодарен за любую помощь.


DimOk   (2007-06-28 09:55:00) [41]


> Ну, если канонически, то так:
> str_pass := StrNew(frmSettingsFilesAndDB.PasswordArc.Text);
>
> После того как str_pass перестанет быть нужной, необходимо
> освободить занятую ей память:
> StrDispose(str_pass);


При условии того что str_pass будет иметь тип PChar или ShortString?


Сергей М.   (2007-06-28 09:55:00) [42]

iniFile.WriteString('ReportSection','PassReport', Encrypt(PChar(frmSettingsFilesAndDB.PasswordArc.Text),135)));


DimOk   (2007-06-28 09:53:00) [43]


> А вообще, теорию надо читать, а не пытаться слепить из разных
> примеров нечто работоспособное... примеры хороши только
> как иллюстрация к теории, а если вы видите пример, но не
> понимаете, как он работает, копировать из него код весьма
> неосмотрительно...

Программа работоспособна, все вот эти примочки чисто для балды, я пытаюсь записать пароль на архив и SMTP сервер в файл INI в закодированном виде, поэтому использую такую шнягу. И сначало эти функции были реализованы в программном юните, а за тем я решил что было бы неплохо запихнуть их в DLL, мало ли придется менять алгоритм кодирования строк и т.п.


Однокамушкин   (2007-06-28 09:53:00) [44]


> DimOk ©   (28.06.07 09:49) [18]
> А как тогда будет правильно???

Ну, если канонически, то так:
str_pass := StrNew(frmSettingsFilesAndDB.PasswordArc.Text);
После того как str_pass перестанет быть нужной, необходимо освободить занятую ей память:
StrDispose(str_pass);


DimOk   (2007-06-28 09:49:00) [45]


> > str_pass := PChar(frmSettingsFilesAndDB.PasswordArc.Text);
>
>
> Тут сложно сказать наверняка, потому что мне неизвестно,
>  что такое frmSettingsFilesAndDB и PasswordArc, но подозреваю,
>  что frmSettingsFilesAndDB - это форма, а PasswordArc -
> какой-то компонент типа TEdit, расположенный на нём... Text
> возвращает string, причём у вас нет никаких прав делать
> предположения о том, где именно в динамической памяти размещена
> строка, которая здесь возвращается... а может, вообще не
> в динамической памяти, а в сегменте кода, такое тоже бывает.
> .. тем не менее, вы тупо приводите её к PChar, т.е. создаёте
> указатель на эту строку, т.е. получаете указатель неизвестно
> куда... и как потом работать с этой памятью, вы не знаете
> (и никто не знает!): вы не знаете, как её правильно освободить,
>  не знаете, не будет ли она сочтена неиспользуемой и использована
> для размещения чего-то ещё, не знаете даже, разрешено ли
> использовать эту память для записи или только для чтения.
> .. С PChar так работать нельзя, вы сами несёте ответственность
> за правильное выделение памяти для таких строк...

А как тогда будет правильно???


Сергей М.   (2007-06-28 09:41:00) [46]

У тебя как минимум две ошибки - первая см. [6], вторая с разными соглашениями о вызовах.


Однокамушкин   (2007-06-28 09:41:00) [47]


> DimOk ©   (28.06.07 09:21) [12]
> Это в коде основной программы. а в DLL с stdcall

Декларация в DLL должна соответствовать декларации в программе... написать stdcall в DLL, но забыть про неё в программе - самая распространённая ошибка новичков, именно её я и имел ввиду под "накосячили"...

> DimOk ©   (28.06.07 09:07) [11]
> В Delphi я новичок поэтому умнечить не буду, весь код который
> я представил это  коды которые я брал с этого сайта из разных
> статей с небольшой доработкой.

Не знаю, какие статьи вы имеете ввиду, но если бы вы знали, сколько по всему интернету валяется откровенно глупых советов... А самое страшное - брать советы из разных статей, не понимая их... потому что от того, как вы выделяете память для PChar, сильно зависит то, как с ним потом работать... если вы возьмёте выделение памяти из одного примера, а обработку из другого, не факт, что это будет нормально работать...

> Это конечно все супер, но не слова на эти места в коде..
> ......

Ну, попробуем подетальнее...

> str_pass := PChar(frmSettingsFilesAndDB.PasswordArc.Text);

Тут сложно сказать наверняка, потому что мне неизвестно, что такое frmSettingsFilesAndDB и PasswordArc, но подозреваю, что frmSettingsFilesAndDB - это форма, а PasswordArc - какой-то компонент типа TEdit, расположенный на нём... Text возвращает string, причём у вас нет никаких прав делать предположения о том, где именно в динамической памяти размещена строка, которая здесь возвращается... а может, вообще не в динамической памяти, а в сегменте кода, такое тоже бывает... тем не менее, вы тупо приводите её к PChar, т.е. создаёте указатель на эту строку, т.е. получаете указатель неизвестно куда... и как потом работать с этой памятью, вы не знаете (и никто не знает!): вы не знаете, как её правильно освободить, не знаете, не будет ли она сочтена неиспользуемой и использована для размещения чего-то ещё, не знаете даже, разрешено ли использовать эту память для записи или только для чтения... С PChar так работать нельзя, вы сами несёте ответственность за правильное выделение памяти для таких строк...

> Result := S;

Готов спорить, вы не знаете, что после такого присваивания Result и S просто начинают указывать на одну и ту же строку, и все изменения, которые вы делаете с содержимым Result, отражаются на содержимом S, потому что по сути у этих переменных одно содержимое на двоих...

> for I := 1 to Length(S) do begin

Индексы строк PChar, в отличие от string, начинаются не с 1, а с 0... да и использование Length для PChar - штука сомнительная, работать из-за неявного приведения PChar к string будет, но правильнее использовать StrLen...

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


DimOk   (2007-06-28 09:38:00) [48]


> Соглашения о вызовах должны быть одинаковы !!
>
> Либо и там и там д.б. указано stdcall (или иное), либо ни
> там ни там не должно фигурировать.
>

Если честно то пробовал и так и так, не помогло, причем и без объявления stdcall я входил в нужную функцию и она выполнялась, но спасибо за просвещение.


Сергей М.   (2007-06-28 09:36:00) [49]


> Это в коде основной программы. а в DLL с stdcall


Соглашения о вызовах должны быть одинаковы !!

Либо и там и там д.б. указано stdcall (или иное), либо ни там ни там не должно фигурировать.


DimOk   (2007-06-28 09:31:00) [50]


> Есть два строковых типа, передача которых между программой
> > и DLL абсолютно безопасна - это ShortString и WideString

При использовании первого у меня программа зависает вернее выдает ошибку которая только снимается через диспетчер задач, а WideString в моем случае не подходит.


DimOk   (2007-06-28 09:21:00) [51]


> А где stdcall в декларации ? Мыши съели ?)

Это в коде основной программы. а в DLL с stdcall


DimOk   (2007-06-28 09:07:00) [52]


> Есть два строковых типа, передача которых между программой
> и DLL абсолютно безопасна - это ShortString и WideString,
>  но первый из них имеет ограничения по длине, да и память
> не очень эффективно расходует, а второй содержит символы
> в двухбайтной кодировке - дельфя их, конечно, где надо сама
> перекодирует в ANSI, но процессороное время при этом будет
> зря кушаться...

В Delphi я новичок поэтому умнечить не буду, весь код который я представил это  коды которые я брал с этого сайта из разных статей с небольшой доработкой. Когда я рассматривал пример с DLL, то у меня все получалось, а сейчас не могу предположить из за чего у меня такая проблемам.  Да и еще

> Заюзайте ShareMem и используйте обычный string, а то в вашем
> коде слишком много мест, выдающих глобальное непонимание
> того, что такое указатели вообще и PChar в частности...
> тут вам надо разобраться с теорией и потом переписать всё
> с нуля...

Это конечно все супер, но не слова на эти места в коде........


Однокамушкин   (2007-06-28 08:59:00) [53]


> DimOk ©   (28.06.07 08:51) [7]
> беда

Это с английским, видимо, у вас беда... Borland в том комментарии не рекомендует использовать string без ShareMem, а с ShareMem как раз всё будет в порядке... а с PChar можно работать только тогда, когда хорошо понимаешь, как правильно выделять и освобождать память, иначе можно такого наворотить... да и вообще, использование PChar ещё не есть гарантия, что ShareMem не понадобится, в некоторых случаях он и с PChar нужен... Есть два строковых типа, передача которых между программой и DLL абсолютно безопасна - это ShortString и WideString, но первый из них имеет ограничения по длине, да и память не очень эффективно расходует, а второй содержит символы в двухбайтной кодировке - дельфя их, конечно, где надо сама перекодирует в ANSI, но процессороное время при этом будет зря кушаться...


Сергей М.   (2007-06-28 08:57:00) [54]


> DimOk ©   (28.06.07 08:54) [8]
>
>


А где stdcall в декларации ? Мыши съели ?)


DimOk   (2007-06-28 08:54:00) [55]


> А ещё напишите, как в программе объявлена процедурная переменная
> Encrypt, а то есть подозрение, что там вы тоже накосячили.
> ..

........
var:
 Encrypt: function(const S: PChar; Key: Word): PChar;


DimOk   (2007-06-28 08:51:00) [56]

> Заюзайте ShareMem и используйте обычный string, а то в вашем
> коде слишком много мест, выдающих глобальное непонимание
> того, что такое указатели вообще и PChar в частности...
> тут вам надо разобраться с теорией и потом переписать всё
> с нуля...

беда
При работе с DLL переменные типа String использовать сам Borland не рекомендует - это можно посмотреть в описание кода сгенерированным конструктором DLL проекта, и там же рекомендации что желательно использовать PChar или ShortString но со вторым такая же


Сергей М.   (2007-06-28 08:07:00) [57]


> str_pass := PChar(frmSettingsFilesAndDB.PasswordArc.Text);


"Косяк" здесь.

После выполнения этой строчки str_pass указывает на уже не существующую строку.


Dimaxx   (2007-06-28 01:04:00) [58]

"Борман" для этих целей рекомендует использовать shortstring - хватает за глаза и за уши.


Однокамушкин   (2007-06-27 19:40:00) [59]

Заюзайте ShareMem и используйте обычный string, а то в вашем коде слишком много мест, выдающих глобальное непонимание того, что такое указатели вообще и PChar в частности... тут вам надо разобраться с теорией и потом переписать всё с нуля...

А ещё напишите, как в программе объявлена процедурная переменная Encrypt, а то есть подозрение, что там вы тоже накосячили...


DimOk   (2007-06-27 17:45:00) [60]

Отрывок с основной программы
//Кодирование//////////////////////////////////////////////////////////////
 @Encrypt := nil;                                                         //
 LibHandle := LoadLibrary('PassDLL.DLL');                                 //
 if LibHandle >= 32 then                                                  //
 begin                                                                    //
   @Encrypt := GetProcAddress(LibHandle,'Encrypt');                       //
   if @Encrypt <> nil then                                                //
   begin                                                                  //
     str_pass := PChar(frmSettingsFilesAndDB.PasswordArc.Text);           //
     iniFile.WriteString('ReportSection','PassReport',String(Encrypt(str_pass,135)));           //
   end;                                                                   //
   FreeLibrary(LibHandle);                                                //
 end;                                                                     //
 ///////////////////////////////////////////////////////////////////////////

DLL ка

library PassDLL;

uses
 SysUtils, Classes;
const
C1 = 52845;
C2 = 22719;
{Декодирует строку}
function Decrypt(const S: PChar; Key: Word): PChar; stdcall;
var

I: byte;
begin

Result := S;
for I := 1 to Length(S) do begin
Result[I] := char(byte(S[I]) xor (Key shr 8));
Key := (byte(S[I]) + Key) * C1 + C2;
end;
end;

{Кодирует строку}
function Encrypt(const S: PChar; Key: Word): PChar; stdcall;
var

I: byte;
begin

Result := S;
for I := 1 to Length(S) do begin
Result[I] := char(byte(S[I]) xor (Key shr 8));
Key := (byte(Result[I]) + Key) * C1 + C2;
end;
end;

exports Decrypt;
exports Encrypt;
begin
end.


Страницы:   1 2 3 4

Наверх

Титульная страница Поиск, карта сайта Написать письмо