Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2007.07.22;
Скачать: [xml.tar.bz2];

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.58 MB
Время: 0.04 c
15-1182797534
AlexKniga
2007-06-25 22:52
2007.07.22
Срочно нужен адрес публичного SMTP сервера


2-1182949731
DimOk
2007-06-27 17:08
2007.07.22
DLL в Delphi


15-1182203401
SerJaNT
2007-06-19 01:50
2007.07.22
Сеть...


15-1182859309
Ega23
2007-06-26 16:01
2007.07.22
Хочу редактор классов для Delphi 7


15-1181763740
Yanis
2007-06-13 23:42
2007.07.22
На чём всё?





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский