Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.07.22;
Скачать: CL | DM;

Вниз

DLL в Delphi   Найти похожие ветки 

 
DimOk ©   (2007-06-27 17:08) [0]

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


 
tesseract ©   (2007-06-27 17:38) [1]


> , может кто знает как устранить такую проблему. Буду очень
> благодарен за любую помощь.


Код в студию, есть предположение, что ты не так указатель передаёшь.


 
Eraser ©   (2007-06-27 17:43) [2]

> [0] DimOk ©   (27.06.07 17:08)

каким образом выделяется память для PChar?


 
DimOk ©   (2007-06-27 17:45) [3]

Отрывок с основной программы
//Кодирование//////////////////////////////////////////////////////////////
 @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.


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

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

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


 
Dimaxx ©   (2007-06-28 01:04) [5]

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


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


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


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

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


 
DimOk ©   (2007-06-28 08:51) [7]

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

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


 
DimOk ©   (2007-06-28 08:54) [8]


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

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


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


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


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


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


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

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


 
DimOk ©   (2007-06-28 09:07) [11]


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

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

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

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


 
DimOk ©   (2007-06-28 09:21) [12]


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

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


 
DimOk ©   (2007-06-28 09:31) [13]


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

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


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


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


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

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


 
DimOk ©   (2007-06-28 09:38) [15]


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

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


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


> 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...

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


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

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


 
DimOk ©   (2007-06-28 09:49) [18]


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

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


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


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

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


 
DimOk ©   (2007-06-28 09:53) [20]


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

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


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

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


 
DimOk ©   (2007-06-28 09:55) [22]


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


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


 
DimOk ©   (2007-06-28 09:59) [23]


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

Нет, я тоже так делал, тут все дело с правильным выделением памяти, я так понял.


 
Сергей М. ©   (2007-06-28 10:01) [24]


> DimOk ©   (28.06.07 09:55) [22]


Еще одна допущенная тобой ошибка - индексация элементов массива символов, на который ссылается PChar-указатель, начинается с нуля а не с единицы.


 
DimOk ©   (2007-06-28 10:03) [25]


> Еще одна допущенная тобой ошибка - индексация элементов
> массива символов, на который ссылается PChar-указатель,
> начинается с нуля а не с единицы.

Это я уже исправил


 
Сергей М. ©   (2007-06-28 10:05) [26]


> DimOk ©   (28.06.07 09:59) [23]


> тут все дело с правильным выделением памяти


Не надо тут ничего выделять.

Время жизни строки, возвращаемой обращением к св-ву Text, равно времени исполнения строки, в котором присутствует это обращение.


 
icWasya ©   (2007-06-28 10:16) [27]

за основу можно взять прототип CharToOemBuff и сделать так

{Кодирует строку}
function Encrypt(Src: PChar; Dest:PChar; ScrLen:Integer; Key: Word);stdcall;
var
 I: byte;
begin
 for I := 0 to SrcLen do begin
    Dest[I] := char(byte(Src[I]) xor (Key shr 8));
    Key := (byte(Result[I]) + Key) * C1 + C2;
 end;
end;


и использовать так

var
 StrSrc:String;
 StrDest:String;

StrSrc:= frmSettingsFilesAndDB.PasswordArc.Text;          
SetLength(StrDest,Length(StrSrc));

Encrypt(Pchar(StrSrc),Pchar(StrDest),Length(StrSrc),135);

iniFile.WriteString("ReportSection","PassReport",StrDest);          


 
DimOk ©   (2007-06-28 10:22) [28]


> за основу можно взять прототип CharToOemBuff и сделать так
>
> {Кодирует строку}
> function Encrypt(Src: PChar; Dest:PChar; ScrLen:Integer;
>  Key: Word);stdcall;
> var
>  I: byte;
> begin
>  for I := 0 to SrcLen do begin
>     Dest[I] := char(byte(Src[I]) xor (Key shr 8));
>     Key := (byte(Result[I]) + Key) * C1 + C2;
>  end;
> end;
>
> и использовать так
>
> var
>  StrSrc:String;
>  StrDest:String;
>
> StrSrc:= frmSettingsFilesAndDB.PasswordArc.Text;        
>  
> SetLength(StrDest,Length(StrSrc));
>
> Encrypt(Pchar(StrSrc),Pchar(StrDest),Length(StrSrc),135);
>
>
> iniFile.WriteString("ReportSection","PassReport",StrDest);
>          
>


Спасибо сейчас ппробую....


 
icWasya ©   (2007-06-28 10:50) [29]

Ошибочка
вместо
for I := 0 to SrcLen do begin
надо
for I := 0 to SrcLen-1 do begin


 
DimOk ©   (2007-06-28 10:58) [30]


> за основу можно взять прототип CharToOemBuff и сделать так
>
> {Кодирует строку}
> function Encrypt(Src: PChar; Dest:PChar; ScrLen:Integer;
>  Key: Word);stdcall;
> var
>  I: byte;
> begin
>  for I := 0 to SrcLen-1 do begin
>     Dest[I] := char(byte(Src[I]) xor (Key shr 8));
>     Key := (byte(Result[I]) + Key) * C1 + C2;
>  end;
> end;
>
> и использовать так
>
> var
>  StrSrc:String;
>  StrDest:String;
>
> StrSrc:= frmSettingsFilesAndDB.PasswordArc.Text;        
>  
> SetLength(StrDest,Length(StrSrc));
>
> Encrypt(Pchar(StrSrc),Pchar(StrDest),Length(StrSrc),135);
>
>
> iniFile.WriteString("ReportSection","PassReport",StrDest);
>  


Такая же фигня получается... :(


 
Сергей М. ©   (2007-06-28 11:20) [31]

в хост-приложении:

TEncrypt = procedure(Buf: PChar; Key: Word); stdcall;
..
var
 Encrypt: TEncrypt;
 tmpstr: String;
..
 tmpstr := frmSettingsFilesAndDB.PasswordArc.Text;
 Encrypr(PChar(tmpstr), 135);
 frmSettingsFilesAndDB.PasswordArc.Text := tmpstr;
 

в библиотеке:

procedure Encrypt(Buf: PChar; Key: Word); stdcall;
var
i: byte;
begin
 i := 0;
 while Buf[i] <> #0 do begin
   Buf[i] := char(byte(Buf[i]) xor (Key shr 8));
   Key := (byte(Buf[i]) + Key) * C1 + C2;
   Inc(i);
 end;
end;


 
Сергей М. ©   (2007-06-28 11:24) [32]


> i: byte;


Правильней будет i: Integer


 
DimOk ©   (2007-06-28 11:34) [33]


> TEncrypt = procedure(Buf: PChar; Key: Word); stdcall;
> ..
> var
>  Encrypt: TEncrypt;
>  tmpstr: String;
> ..
>  tmpstr := frmSettingsFilesAndDB.PasswordArc.Text;
>  Encrypr(PChar(tmpstr), 135);
>  frmSettingsFilesAndDB.PasswordArc.Text := tmpstr;

Пишет Invalid Pointer Operation


 
Сергей М. ©   (2007-06-28 11:41) [34]

Ну что ты как детский ребенок, ей-богу ?

На какой строчке "пишет" ?


 
Anatoly Podgoretsky ©   (2007-06-28 11:49) [35]

Хочешь хороший совет - забудь про DLL и PChar
Это пока не твое.


 
DimOk ©   (2007-06-28 11:55) [36]


> Хочешь хороший совет - забудь про DLL и PChar
> Это пока не твое.


Пришел за помощью, а вы меня отфутболиваете, зачем тогда этот форум существует? Обсирать новичков? Или давать все же помогать......?  Вы сами проверяете свои советы или так из гоовы их бирете.....?Хорошо поппытаю счастья где ни будь в другом месте.


 
Сергей М. ©   (2007-06-28 12:03) [37]


> поппытаю счастья где ни будь в другом месте


Проконсультируйся насчет "другого места" у Ketmar (C) - от точно подскажет, куда тебе идти


 
Сергей М. ©   (2007-06-28 12:12) [38]


> DimOk ©   (28.06.07 11:55) [36]


У тебя автомобиль есть ?


 
DimOk ©   (2007-06-28 12:16) [39]


> У тебя автомобиль есть ?

Нет


 
Сергей М. ©   (2007-06-28 12:20) [40]

Жаль. Пример обращения тебя как автовладельца "больного" авто, в котором ты ничерта не смыслишь (но в душе искренне желаешь познать), к специалистам автосервиса был бы весьма показателен.



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

Текущий архив: 2007.07.22;
Скачать: CL | DM;

Наверх




Память: 0.6 MB
Время: 0.023 c
1-1179320420
Alexys
2007-05-16 17:00
2007.07.22
списки


2-1183120042
Nikfel
2007-06-29 16:27
2007.07.22
Прозрачный текст на canvas.


3-1177065675
_andrews_
2007-04-20 14:41
2007.07.22
BLOB to string


15-1182440840
oxffff
2007-06-21 19:47
2007.07.22
steve trefethen покидает codegear


15-1182388452
FBuilder
2007-06-21 05:14
2007.07.22
kiusercallbackdispatcher или почему висим?