Форум по Delphi программированию

Delphi Sources



Вернуться   Форум по Delphi программированию > Все о Delphi > [ "Начинающим" ]
Ник
Пароль
Регистрация <<         Правила форума         >> FAQ Пользователи Календарь Поиск Сообщения за сегодня Все разделы прочитаны

Закрытая тема
 
Опции темы Поиск в этой теме Опции просмотра
  #1  
Старый 29.10.2015, 23:28
Аватар для Homo-Fantasmus
Homo-Fantasmus Homo-Fantasmus вне форума
Прохожий
 
Регистрация: 23.08.2011
Адрес: МО
Сообщения: 46
Версия Delphi: Delphi, Lazarus
Репутация: 10
По умолчанию Нужна помощь с dll

Всем привет!
Первый опыт работы с dll, нашёл подробный пример создания, подключения и работы с dll на сайте pro.dtn.ru.

Сделал всё как в примере:
1)Объявил процедурную переменную или процедурный тип, описывающий подпрограмму, которую нужно вызвать.
2)Вызвал функцию LoadLibrary для загрузки библиотеки DLL.
3)Вызвал функцию GetProcAddress для получения указателя на подпрограмму в библиотеке DLL.
4)Вызвал подпрограмму.
5)Вызвал функцию FreeLibrary для выгрузки библиотеки DLL.

Выскакивает ошибка, не могу понять где накосячил или глаз уже замылился - не вижу.


Короче, по порядку:

Есть форма с большим количеством текстовых полей, и есть кусок кода который не даёт вводить в Edit что-либо кроме чисел действительных или целых.

Реализовано это так:
Код:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
    rez:string;
    znak,key: char;
 
begin
rez:= FloatToStr(1/2);
rez:= copy(rez,2,1);
znak:= rez[1];
 
if (key = '.') and (key <> znak)  then
key:=znak;
 
if (key = ',') and (key <> znak)  then
key:=znak;
 

 if key  in ['a'..'z'] then
key := #0;    //Не даёт вводить буквы из множества a-z

if (key = 'й')or(key = 'ц') or(key = 'у') or(key = 'к')or(key = 'е')or(key = 'н')
or(key = 'г')or(key = 'ш')or(key = 'щ')or(key = 'з')or(key = 'х')or(key = 'ъ')
or(key = 'ф')or(key = 'ы')or(key = 'в')or(key = 'а')or(key = 'п')or(key = 'р')
or(key = 'о')or(key = 'л')or(key = 'д')or(key = 'ж')or(key = 'э')or(key = 'я')
or(key = 'ч')or(key = 'с')or(key = 'м')or(key = 'и')or(key = 'т')or(key = 'ь')
or(key = 'б')or(key = 'ю')then
key := #0;

 if  (key = '\')or (key = '/') or (key = '*')or (key = '+') or
 (key = '-')or (key = '`')or (key = '=')or (key = '[')or
 (key = ']')or (key = ';')or (key = '!')or (key = '@')or (key = '#')
 or (key = '$')or (key = '%')or (key = '^')or (key = '&')or (key = '(')
 or (key = ')')or (key = '_')or (key = '`')then
 key := #0;  //Не даёт вводить арифмет. символы
  }
 end;

Этот фрагмент в коде программы повторяется очень часто, что делает код громоздким и трудночитаемым.

Поэтому я решил засунуть этот фрагмент в dll в виде процедуры и вызывать её когда мне нужно.

реализовано это так:
Код:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
DLLRoutine: procedure; //объявление процедурной переменной
DllHandle: THandle;

begin
   try
   //Загружаем 'Tube_Smoke.dll'
    DLLHandle := LoadLibrary('Tube_Smoke.dll');
    finally
    FreeLibrary(DLLHandle);
    ShowMessage('Не удалось загрузить DLL ...');
    end;

    try
    { DLLRoutine указывает на процедуру 'Check_Edit' в файле 'Tube_Smoke.dll' }
    DLLRoutine := GetProcAddress(DLLHandle,'Check_Edit');

    { Вызываем процедуру 'Check_Edit' }
    if Assigned(DLLRoutine) then
      DLLRoutine;

    if   GetProcAddress(DLLHandle,'Check_Edit') = nil then
      ShowMessage('Не удалось получить доступ к процедуре...');
      finally
    FreeLibrary(DLLHandle);

  end; // Конец блока try..finally
  end;

Файл dll кинул в папку проекта и в папку debug где эгзешник.
Сама dll:
Код:
library Tube_Smoke;

{ Important note about DLL memory management: ShareMem must be the
  first unit in your library's USES clause AND your project's (select
  Project-View Source) USES clause if your DLL exports any procedures or
  functions that pass strings as parameters or function results. This
  applies to all strings passed to and from your DLL--even those that
  are nested in records and classes. ShareMem is the interface unit to
  the BORLNDMM.DLL shared memory manager, which must be deployed along
  with your DLL. To avoid using BORLNDMM.DLL, pass string information
  using PChar or ShortString parameters. }



uses
  System.SysUtils,System.Classes;

{$R *.res}



procedure Check_Edit;
 var
    rez:string;
    znak,key: char;

begin

rez:= FloatToStr(1/2);
rez:= copy(rez,2,1);
znak:= rez[1];

if (key = '.') and (key <> znak)  then
key:=znak;

if (key = ',') and (key <> znak)  then
key:=znak;

 if key  in ['a'..'z'] then
key := #0;    //Не даёт вводить буквы из множества a-z


if (key = 'й')or(key = 'ц') or(key = 'у') or(key = 'к')or(key = 'е')or(key = 'н')
or(key = 'г')or(key = 'ш')or(key = 'щ')or(key = 'з')or(key = 'х')or(key = 'ъ')
or(key = 'ф')or(key = 'ы')or(key = 'в')or(key = 'а')or(key = 'п')or(key = 'р')
or(key = 'о')or(key = 'л')or(key = 'д')or(key = 'ж')or(key = 'э')or(key = 'я')
or(key = 'ч')or(key = 'с')or(key = 'м')or(key = 'и')or(key = 'т')or(key = 'ь')
or(key = 'б')or(key = 'ю')then
key := #0;

 if  (key = '\')or (key = '/') or (key = '*')or (key = '+') or
 (key = '-')or (key = '`')or (key = '=')or (key = '[')or
 (key = ']')or (key = ';')or (key = '!')or (key = '@')or (key = '#')
 or (key = '$')or (key = '%')or (key = '^')or (key = '&')or (key = '(')
 or (key = ')')or (key = '_')or (key = '`')then
 key := #0;  //Не даёт вводить арифмет. символы

 end;

 exports
 Check_Edit;


begin
end.

Срабатывает обработчик исключений. Не пойму почему...
И так и сяк вертел.... И через функцию пробовал...
Может кто ни будь, кинет на форму один Edit и попробует "исполнить" так сказать на бис ?
Вложения
Тип файла: 7z DLL TubeSmoke.7z (818.5 Кбайт, 0 просмотров)
__________________
Как завещал товарищ Ленин: УЧИТЬСЯ! УЧИТСЯ! И ЕЩЁ РАЗ УЧИЦЦА!
  #2  
Старый 30.10.2015, 00:12
Аватар для Verevkin
Verevkin Verevkin вне форума
Прохожий
 
Регистрация: 22.06.2015
Сообщения: 45
Версия Delphi: 3...XE12
Репутация: -50
По умолчанию

Посмотрел твой исходник.
Это шутка, да?
До 1 апреля, вроде, далековато.
__________________
Хей-хей-хей! Только не ходите в мой сарай, лады?..
  #3  
Старый 30.10.2015, 08:13
Аватар для NumLock
NumLock NumLock вне форума
Let Me Show You
 
Регистрация: 30.04.2010
Адрес: Северодвинск
Сообщения: 5,426
Версия Delphi: 7, XE5
Репутация: 59586
По умолчанию

Код:
try
   //Загружаем 'Tube_Smoke.dll'
    DLLHandle := LoadLibrary('Tube_Smoke.dll');
    finally
    FreeLibrary(DLLHandle);
    ShowMessage('Не удалось загрузить DLL ...');
    end;
 
    try
    { DLLRoutine указывает на процедуру 'Check_Edit' в файле 'Tube_Smoke.dll' }
    DLLRoutine := GetProcAddress(DLLHandle,'Check_Edit');
 
    { Вызываем процедуру 'Check_Edit' }
    if Assigned(DLLRoutine) then
      DLLRoutine;
загружаешь библиотеку и сразу же ее освобождаешь, а потом начинаешь использовать!!!
__________________
Пишу программы за еду.
__________________
  #4  
Старый 30.10.2015, 14:50
icWasya icWasya вне форума
Местный
 
Регистрация: 09.11.2010
Сообщения: 499
Репутация: 10
По умолчанию

В первом примере- что делает в процедуре локальная переменная key, которая имеет то же имя, что и формальный параметр?

во втором примере, а где параметры процедуры?
  #5  
Старый 30.10.2015, 17:47
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,096
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Извращенцы. Микроскопом гвозди забивать не пробовали? Говорят, тоже хорошо вставляет, особенно когда осколки линз во все стороны летят...

Для данной задачи не нужно ничего, кроме ОДНОГО простого обработчика, присвоенного ВСЕМ едитам.

Код:
procedure TForm1.EditKeyPress(Sender : TObject; var Key : Char);
begin
  if Not (Key In ['0'..'9','.',#8])
    Then Key := #0
    Else
      If Key = '.' Then
        If Pos('.',(Sender As TEdit).Text) > 0 Then Key := #0;
end;
И присвой этот обработчик всем едитам в OnKeyPress.
  #6  
Старый 30.10.2015, 22:51
Аватар для Homo-Fantasmus
Homo-Fantasmus Homo-Fantasmus вне форума
Прохожий
 
Регистрация: 23.08.2011
Адрес: МО
Сообщения: 46
Версия Delphi: Delphi, Lazarus
Репутация: 10
По умолчанию

to NumLock

Не понял, почему я её сразу же освобождаю ?!? Я её освобождаю только если не удалось выполнить
Код:
DLLHandle := LoadLibrary('Tube_Smoke.dll');
т.е. только если при загрузке библиотеки возникла ошибка
__________________
Как завещал товарищ Ленин: УЧИТЬСЯ! УЧИТСЯ! И ЕЩЁ РАЗ УЧИЦЦА!

Последний раз редактировалось Homo-Fantasmus, 30.10.2015 в 22:54.
  #7  
Старый 30.10.2015, 23:07
Аватар для Homo-Fantasmus
Homo-Fantasmus Homo-Fantasmus вне форума
Прохожий
 
Регистрация: 23.08.2011
Адрес: МО
Сообщения: 46
Версия Delphi: Delphi, Lazarus
Репутация: 10
По умолчанию

Цитата:
Сообщение от Verevkin
Посмотрел твой исходник.
Это шутка, да?
До 1 апреля, вроде, далековато.

В исходнике только проект библиотеки ...
Сарказм по поводу отсутствия основного проекта или c dll всё так плохо?

Основной проект много весит.
Кинь на форму один Edit и попробую по событию OnKeyPress выполнить процедуру из dll.
__________________
Как завещал товарищ Ленин: УЧИТЬСЯ! УЧИТСЯ! И ЕЩЁ РАЗ УЧИЦЦА!
  #8  
Старый 30.10.2015, 23:14
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Цитата:
т.е. только если при загрузке библиотеки возникла ошибка
Внимательно прочитай, что такое пара try/finally и чем отличается блок finally от блока except.
А вообще-то lmikle совершенно прав.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
  #9  
Старый 30.10.2015, 23:36
Аватар для Homo-Fantasmus
Homo-Fantasmus Homo-Fantasmus вне форума
Прохожий
 
Регистрация: 23.08.2011
Адрес: МО
Сообщения: 46
Версия Delphi: Delphi, Lazarus
Репутация: 10
По умолчанию

Цитата:
Сообщение от lmikle
Извращенцы. Микроскопом гвозди забивать не пробовали? Говорят, тоже хорошо вставляет, особенно когда осколки линз во все стороны летят...

Для данной задачи не нужно ничего, кроме ОДНОГО простого обработчика, присвоенного ВСЕМ едитам.

Код:
procedure TForm1.EditKeyPress(Sender : TObject; var Key : Char);
begin
  if Not (Key In ['0'..'9','.',#8])
    Then Key := #0
    Else
      If Key = '.' Then
        If Pos('.',(Sender As TEdit).Text) > 0 Then Key := #0;
end;
И присвой этот обработчик всем едитам в OnKeyPress.

От тиражирования одного и того-же фрагмента кода я как раз и пытаюсь уйти , а ты мне предлагаешь те-же яйца только в профиль - "присвой этот обработчик всем едитам"

Твой код на первый взгляд оптимизирован лучше...

но во первых
знак разделения дробных чисел может быть не "." а "," - это зависит от настроек конкретной ОС, а для меня важно что-бы они совпадали;
во вторых защита от ввода не нужных символов в данном случае не самоцель.

Главное хотелось бы освоить работу с DLL...
С чего-то начинать нужно..
  #10  
Старый 30.10.2015, 23:39
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Цитата:
знак разделения дробных чисел может быть не "." а "," - это зависит от настроек конкретной ОС, а для меня важно что-бы они совпадали;
Читаем про DecimalSeparator и добавляем его во множество допустимых символов. Если при вводе одного должно вводиться другое - подменить отдельно в этой же функции. Типа
Код:
if (key in ['.',',']) and (key <> DecimalSeparator) then
    key := DecimalSeparator;
И присвоить один обработчик - это не тиражирование. Код физически будет один, просто в Sender ему будет передаваться разный Edit.
Цитата:
Главное хотелось бы освоить работу с DLL...
Это уже другой вопрос. На него ответил NumLock.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.

Последний раз редактировалось Bargest, 30.10.2015 в 23:44.
  #11  
Старый 31.10.2015, 00:07
Аватар для Homo-Fantasmus
Homo-Fantasmus Homo-Fantasmus вне форума
Прохожий
 
Регистрация: 23.08.2011
Адрес: МО
Сообщения: 46
Версия Delphi: Delphi, Lazarus
Репутация: 10
По умолчанию

Цитата:
Сообщение от Bargest
Внимательно прочитай, что такое пара try/finally и чем отличается блок finally от блока except.
А вообще-то lmikle совершенно прав.

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

Заменил на except.

Код:
procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
var
DLLRoutine: procedure; //объявление процедурной переменной
DllHandle: THandle;

begin
   try
   //Загружаем 'Tube_Smoke.dll'
    DLLHandle := LoadLibrary('Tube_Smoke.dll');
  except
    FreeLibrary(DLLHandle);
    ShowMessage('Не удалось загрузить DLL ...');
    end;

    try
    { DLLRoutine указывает на процедуру 'Check_Edit' в файле 'Tube_Smoke.dll' }
    DLLRoutine := GetProcAddress(DLLHandle,'Check_Edit');

    { Вызываем процедуру 'Check_Edit' }
    if Assigned(DLLRoutine) then
      DLLRoutine;

    if   GetProcAddress(DLLHandle,'Check_Edit') = nil then
      ShowMessage('Не удалось получить доступ к процедуре...');
     except
    FreeLibrary(DLLHandle);

  end;
  end;

Компилирует без ошибок, но и процедура не работает - в Edit удаётся забить буквы и арифметические символы.
  #12  
Старый 31.10.2015, 00:14
Аватар для Bargest
Bargest Bargest вне форума
Профессионал
 
Регистрация: 19.10.2010
Адрес: Москва
Сообщения: 2,390
Версия Delphi: XE3/VS12/FASM
Репутация: 14665
По умолчанию

Ну еще бы она работала. Вызывается процедура, в какую-то свою локальную переменную что-то зачем-то пишет. И? Она даже не принимает на вход нажатую клавишу, не говоря уже о каких-то выходных результатах.
__________________
jmp $ ; Happy End!
The Cake Is A Lie.
  #13  
Старый 31.10.2015, 00:30
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,096
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от Homo-Fantasmus
От тиражирования одного и того-же фрагмента кода я как раз и пытаюсь уйти , а ты мне предлагаешь те-же яйца только в профиль - "присвой этот обработчик всем едитам"

Твой код на первый взгляд оптимизирован лучше...

но во первых
знак разделения дробных чисел может быть не "." а "," - это зависит от настроек конкретной ОС, а для меня важно что-бы они совпадали;
во вторых защита от ввода не нужных символов в данном случае не самоцель.

Главное хотелось бы освоить работу с DLL...
С чего-то начинать нужно..

1. Ну используй вместо '.' DecimalSeparator, эта константа как раз и инициализируется из сиситемных настроек.
2. Кто тебе сказал, что надо РАЗМНОЖИТЬ этот код? Это ОДИН обработчик, который просто надо указать в OnKeyPress ВСЕХ едитов. Просто тупо выдели все едиты и в ObjectInspector'е укажи имя этой процедуры для OnKeyPress. Сам код только в одном месте обращается к едиту и это прописано через Sender, так что он, код, не зависит от конкретного эдита, работает с тем, который и вызвал событие...
3. Как раз эта задача вообще не для DLL, для DLL придумай другую задачу. Тут накладных расходов в DLL больше получается, чем даже если ты начнешь размножать свой вариант кода.

ЗЫ. А еще есть статическая загрузка DLL, когда эти танцы с LoadLibrary/GetProcAddress/FreeLibrary просто не нужны. Но там все прибито гвоздями...

Последний раз редактировалось lmikle, 31.10.2015 в 00:33.
  #14  
Старый 31.10.2015, 00:36
Аватар для Homo-Fantasmus
Homo-Fantasmus Homo-Fantasmus вне форума
Прохожий
 
Регистрация: 23.08.2011
Адрес: МО
Сообщения: 46
Версия Delphi: Delphi, Lazarus
Репутация: 10
По умолчанию

Цитата:
Сообщение от Bargest
Ну еще бы она работала. Вызывается процедура, в какую-то свою локальную переменную что-то зачем-то пишет. И? Она даже не принимает на вход нажатую клавишу, не говоря уже о каких-то выходных результатах.

Да, плохо быть бестолковым...

Т.е. мне нужно записать в переменную из основной программы код нажатой клавиши, в dll как-то прочитать его, обработать и вернуть назад результат.
Такой алгоритм ?
__________________
Как завещал товарищ Ленин: УЧИТЬСЯ! УЧИТСЯ! И ЕЩЁ РАЗ УЧИЦЦА!
  #15  
Старый 31.10.2015, 00:48
lmikle lmikle вне форума
Модератор
 
Регистрация: 17.04.2008
Сообщения: 8,096
Версия Delphi: 7, XE3, 10.2
Репутация: 49089
По умолчанию

Цитата:
Сообщение от Bargest
Ну еще бы она работала. Вызывается процедура, в какую-то свою локальную переменную что-то зачем-то пишет. И? Она даже не принимает на вход нажатую клавишу, не говоря уже о каких-то выходных результатах.

А особенно смешно выглядит вот это:
Код:
try
   //Загружаем 'Tube_Smoke.dll'
    DLLHandle := LoadLibrary('Tube_Smoke.dll');
  except
    FreeLibrary(DLLHandle);
    ShowMessage('Не удалось загрузить DLL ...');
    end;
Код в except вообще никогда не выполнится
И это хорошо, бо как фиг его знает, что он попытается освободить по DLLHandle = 0. Хорошо, если просто проигнорирует вызов.
А потом код пойдет дальше и будет пытаться у того же модуля с хэндлом = 0 получить адрес процедуры... ну вы поняли...

Кароче, вот если уж так хочется делать через одно место, то:
Код:
type
  TEditKeyPressCheck = function (AText: String; AKey : Char) : Char;

procedure TForm1.Edit1KeyPress(Sender : TObject; Key : Char);
var
  AHandle : THandle;
  Proc : TEditKeyPressCheck;
begin
  Try
    AHandle := LoadLibrary('...');
    If AHandle = 0 Then Raise Exception.Create('Oops... can''t load library.');

    Try
      Proc := GetProcAddress(AHandle,'Check_Edit');
      If Proc = Nil Then Raise Exception.Create('Oops.. can''t find function.');

      Key := Proc((Sender As TEdit).Text,Key);
    Finally
      FreeLibrary(AHandle);
    End;
  Except
   On E : Exception Do
     Begin
       ShowMessage(E.Message);
       Key := #0;
     End;
  End;
end;
Ну а что в библитечной функции писать - сам разберешься...
Этот пользователь сказал Спасибо lmikle за это полезное сообщение:
Homo-Fantasmus (31.10.2015)
Закрытая тема


Delphi Sources

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать темы
Вы не можете отвечать на сообщения
Вы не можете прикреплять файлы
Вы не можете редактировать сообщения

BB-коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход


Часовой пояс GMT +3, время: 03:20.


 

Сайт

Форум

FAQ

Соглашения

Прочее

 

Copyright © Форум "Delphi Sources" by BrokenByte Software, 2004-2025