Форум: "Начинающим";
Текущий архив: 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.041 c