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

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

Как правильно вызывать функцию из ДЛЛ?


alles ©   (2006-08-30 17:22:00) 

Здраствуйте.
Ребята, пожалуста скажите как правильно вызывать функцию из ДЛЛ.
В ДЛЛ имеем
function MessageDetails(FileName:ShortString):TPackageMessageDetails;export; stdcall;
var MessageText:String;
   i,j:integer;
begin
MessageText:=LOADFROMFILE(FileName);
if (Copy(MessageText,i,4)=':21:') then
                                   begin
                                        Inc(Result.NrMessages);
                                        SetLength(Result.IDoc,Result.NrMessages);
                                        Result.IDoc[Result.NrMessages-1]:='';
                                        j:=i+4;
                                        while (MessageText[j]<>':') do
                                                            begin
                                                                 Result.IDoc[Result.NrMessages-1]:=Result.IDoc[Result.NrMessages-1]+MessageText[j];
                                                                 inc(j);
                                                            end;
                                   end;
end;

exports
MessageDetails;


и рекорд

type TPackageMessageDetails=record
    NrMessages:byte;
    IDoc: array of ShortString;
end;


В прожект пишу обьявление функций так
MessageDetails: function (FileName:ShortString):TPackageMessageDetails; stdcall;
Вызываю процедуру из прожекта так

procedure TForm1.btnTestClick(Sender: TObject);
var DLLInstanceRole:THandle;
   a:TPackageMessageDetails;
var I:integer;
begin
DLLInstanceRole := LoadLibrary(PChar(Edit1.Text));
 @MessageDetails := GetProcAddress(DLLInstanceRole, 'MessageDetails');
  if Assigned(@MessageDetails)then
              begin
                  a:= MessageDetails('C:\FV12269363.SWF');
                  Showmessage(a.NrMessages);
             end;
FreeLibrary(DLLInstanceRole);
end;


Если убираю эти строчки из функцию ДЛЛ-а то все работает нормально

           SetLength(Result.IDoc,Result.NrMessages);
           Result.IDoc[Result.NrMessages-1]:='';
           j:=i+4;
           while (MessageText[j]<>':') do
             begin
                   Result.IDoc[Result.NrMessages-1]:=Result.IDoc[Result.NrMessages-1]+MessageText[j];
      inc(j);
  end;

то есть как пишу эту строку то прожект показывает сначяло Showmessage(a.NrMessages);
а потом AV
Спасибо


Германн   (2006-08-31 01:41:00) [1]


> Джо ©   (30.08.06 18:13) [5]
>
...
> П.С. Интересно, почему никто не читает длинный и подробный
> комментарий, помещаемый в начало автоматически сгенерированного
> проекта DLL?
>


Так сей текст на аглицком! А у нас до сих пор "чистят кирпичём"! :-)


medved_68   (2006-08-30 22:32:00) [2]


> Все работает.

Это плохо!!!!

> Оказывается что если менять хоть чтото в обьявление рекорда
> в длл или в пожект, то тогда все, кирдык

Это хорошо!!!

> Ничего не показывает

Это плохо!!!!

> Всем спасибо

И тебе тоже мил человек!!!!!


alles   (2006-08-30 19:10:00) [3]

Все работает. Оказывается что если менять хоть чтото в обьявление рекорда в длл или в пожект, то тогда все, кирдык. Ничего не показывает. Всем спасибо


alles   (2006-08-30 18:43:00) [4]

и что странно: если в ДЛЛ пишу
Showmessage(inttostr(Result.NrMessages));
то показывается как Result.NrMessages растет


alles   (2006-08-30 18:40:00) [5]

2 DiamondShark ©   (30.08.06 18:16) [6]
Ну я же не буду писАть весь ДЛЛ сюда
эта строка  
if (Copy(MessageText,i,4)=':21:')находится в цикле
for i:=1 to Length(MessageText) do
А скажите плчему после добавлений шаремем в прожекте и в длл эта строка
Showmessage(a.NrMessages);
возвращяет иероглифы.


DiamondShark   (2006-08-30 18:16:00) [6]


> if (Copy(MessageText,i,4)=':21:')

в этой точке i равно среднесуточной температуре на Марсе за прошлый год в градусах Фаренгейта.

Не знаю, как к этому отнесётся Copy, но, скорее всего, она-таки не вернёт ':21:' в подавляющем большинстве случаев, значит if не выполнится, и Result останется неинициализированным.
Но это ещё пол-беды.

При особо неудачном расположении звёзд тело условного оператора может выполниться.


> Inc(Result.NrMessages);

К счастью, размер в один байт не позволит использовать в качестве значения текущую сумму на счету Била Гейца, выраженную в японских йенах, и оператор

> SetLength(Result.IDoc,Result.NrMessages);

не попытается захватить больше 64кб памяти.


> j:=i+4;
>                                         while (MessageText[j]<>':
> ') do

Хвала Аллаху, вероятность встретить в памяти байт, со значением ':' равна 1/256, а значительная часть ВАП всё-таки доступна для чтения.


> Showmessage(a.NrMessages);

Если это скомпилировалось, то, скорее всего, код компилятора серьёзно повреждён. Стоит попробовать переустановить Дельфи. Возможно, ошибки исчезнут.


Джо   (2006-08-30 18:13:00) [7]


> alles ©   (30.08.06 17:45) [4]
>
> поставил я в uses sharemem.
> Все работает но при закрытий программы пишет invalid pointer
> operation, но это уже другой вопрос

Его нужно поставить ПЕРВЫМ модулем как в DLL, так и в вызывающей программе (в файле dpr).
Кстати, при распространении программы нужно также поставлять файл borlndmm.dll.

П.С. Интересно, почему никто не читает длинный и подробный комментарий, помещаемый в начало автоматически сгенерированного проекта DLL?


alles   (2006-08-30 17:45:00) [8]

поставил я в uses sharemem.
Все работает но при закрытий программы пишет invalid pointer operation, но это уже другой вопрос


alles   (2006-08-30 17:39:00) [9]

нашел в справку

Если Вы используете длинные строки как аргументы или результаты для функций, располагающихся в DLL, то в DLL надо использовать модуль ShareMem;
Не используйте длинные строки как члены структур типа record. Используйте там короткие строки или array[0..n] of char. Также нельзя использовать в структурах типа record динамические массивы. Данные ограничения отсутствуют для классов.

где и как испльзовать модуль ShareMem?


alles   (2006-08-30 17:36:00) [10]

2 han_malign ©
скажите плиз как использовать в данном случяе sharemem


han_malign   (2006-08-30 17:28:00) [11]

type TPackageMessageDetails=record
   NrMessages:byte;
    IDoc: array of ShortString;
end;


- на динамические массивы распространяются те же ограничения, что и на "длинные" строки... То бишь - sharemem...


Наверх

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