Модераторы: Snowy, MetalFan, bems, Poseidon
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Где ошибка в простом варианте DLL. что-то не так с указателями? 
V
    Опции темы
vl1639
Дата 23.10.2009, 17:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.12.2008

Репутация: нет
Всего: нет



Помогите найти ошибку в простом варианте DLL. Для уверенности я проверяю совместную работу сначала как основную программу и функцию в одном файле

Код

program test1;
{$APPTYPE CONSOLE}
uses
  SysUtils;
Type
 pdouble = ^double;
Var 
 ChangeMass :array [1..10] of double;

Function GetSimpleChange( nn :integer; a,b :double ):Pchar; stdcall;
Var
 pdou : pdouble;
 pcha : pChar;
 ii :integer;
begin
  if nn=1 then for ii:=1 to 10 do ChangeMass[ii] := 10*ii + a ;
  if nn>1 then for ii:=1 to 10 do ChangeMass[ii] := 10*ii + b;
  pdou := @ChangeMass[1];
  pcha := pChar(pdou);
  Result := pcha;
end;

var
 ff :textfile;
 pch :pChar;
 buff :array [1..10] of double;
 ii, num :integer;
begin
  { TODO -oUser -cConsole Main : Insert code here }
 AssignFile(ff,'vih.tab'); ReWrite(ff);
 for num:=1 to 2 do begin
           pch := GetSimpleChange(num, 1.0, 5.0);
           move(pch^,buff,sizeof(double)*10);
           for ii:=1 to 5 do Write(ff,buff[ii]:10:2);  Writeln(ff);
  end;
  CloseFile(ff);
end.

Здесь все нормально и печатается, как ожидалось
11.00 21.00 31.00 41.00 51.00
15.00 25.00 35.00 45.00 55.00

Теперь разбиваю задачу на основную прогу и DLL
==Текст DLL 
Код

library mydll;
uses
  SysUtils, Classes;
{$R *.res}
Type
 pdouble = ^double;
Var
 ChangeMass :array [1..10] of double;

Function GetSimpleChange( nn :integer; a,b :double ):Pchar; stdcall;
Var
 pdou : pdouble;
 pcha : pChar;
 ii :integer;
begin
  if nn=1 then for ii:=1 to 10 do ChangeMass[ii] := 10*ii + a ;
  if nn>1 then for ii:=1 to 10 do ChangeMass[ii] := 10*ii + b;
  pdou := @ChangeMass[1];
  pcha := pChar(pdou);
  Result := pcha;
end;

exports GetSimpleChange;
begin
end.

==Текст вызывающей программы
Код

program test1;
{$APPTYPE CONSOLE}
uses
  Windows, Dialogs, SysUtils;
var
  GetSimpleChange:function( nn :integer; a,b :double ):PChar;
  LibHandle :THandle;

var
 ff :textfile;
 pch :pChar;
 buff :array [1..10] of double;
 ii, num :integer;
begin
  { TODO -oUser -cConsole Main : Insert code here }
 for ii:=1 to 10 do buff[ii] :=0.0;
 AssignFile(ff,'vih.tab'); ReWrite(ff);

 @GetSimpleChange := nil;
 LibHandle := LoadLibrary('mydll.dll');
  if ( LibHandle < 32 ) then ShowMessage('Error Load DLL')
  else  begin
   @GetSimpleChange := GetProcAddress(LibHandle,'GetSimpleChange');
   if @GetSimpleChange <> nil then
     begin
       for num:=1 to 2 do begin
           pch := GetSimpleChange(num, 1.0, 5.0);
           move(pch^,buff,sizeof(double)*10);
           for ii:=1 to 5 do Write(ff,buff[ii]:10:2);  Writeln(ff);
       end;
     end;
  end;

  FreeLibrary(LibHandle);
  CloseFile(ff);
end.

Использую загрузку по образцу из Инета, а все остальное как в верхнем примере, а в результате
0.00 0.00 0.00 0.00 0.00
0.00 0.00 0.00 0.00 0.00
Что-то я делаю не так - подскажите!!! 
PM MAIL   Вверх
bems
Дата 24.10.2009, 02:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 3400
Регистрация: 5.1.2006

Репутация: 18
Всего: 88



В вызывающей проге забыл указать конвенцию вызова. И еще какой смысл в привидении указателя на массив даблов к у указателю на символ и обратно?


--------------------
Обижено школьников: 8
PM MAIL   Вверх
vl1639
Дата 24.10.2009, 17:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.12.2008

Репутация: нет
Всего: нет



to bems 
за конвенцию спасибо - не углядел, а в ней зарылась собака. Про указатели - это ведь тренировочный полет. Мне вообще в дальнейшем будет нужно а)использовать именно массив даблов, а если получать указатель на первый дабл массива как Pchar, то  выдается ошибка, отсюда танцы с указателями; б)функция должна будет возвращать именно PChar. 
Вариант Result := @ChangeMass[1]; проходит, но я не уверен в его надежности, а как обработать исключение (если вдруг) - не знаю. Может я опять не вижу более простого решения с указанными условиями, не подскажете ?

Это сообщение отредактировал(а) vl1639 - 24.10.2009, 17:39
PM MAIL   Вверх
CodeMonkey
Дата 24.10.2009, 19:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89





--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
vl1639
Дата 25.10.2009, 11:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.12.2008

Репутация: нет
Всего: нет



to CodeMonkey, 
за ссылки спасибо, понял, что с указателями все разрешено, что истолковывается однозначно. 
Но теперь смутило утверждение в упомянутых текстах по поводу DLL, о том что "...вызывающий обязан подготовить буфер,  и вы избегаете любых проблем с управлением памятью. Если вы предоставляете буфер, то вы и знаете, как его удалять и т.д...". Я предполагал, что в варианте динамической загрузки объявив в DLL  вне функции 
Код

Var
 ChangeMass :array [1..10] of double;

я резервирую память в 10 даблов, данные в которой может изменять только DLL и ее никто не попортит  от момента в вызывающей программе 
Код

LibHandle := LoadLibrary('mydll.dll');

 до  момента в вызывающей программе
Код

FreeLibrary(LibHandle);

Если можно, то без ссылок, просто - это так или я неверно понял смысл механизма подключения DLL? 

PM MAIL   Вверх
CodeMonkey
Дата 25.10.2009, 15:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1839
Регистрация: 24.6.2008
Где: Россия, Тверь

Репутация: 29
Всего: 89



Цитата(vl1639 @  25.10.2009,  11:41 Найти цитируемый пост)
Если можно, то без ссылок, просто - это так или я неверно понял смысл механизма подключения DLL? 

Да нет, поняли правильно, но ваша текущая реализация выглядит очень странно.
Во-первых, множественные (лишние) преобразования типов.
Во-вторых, не проще ли в функцию в DLL передать массив, а уж функция его заполнит? Тогда глобальную переменную можно выкинуть, и результат вызова вы сможете использовать и после выгрузки DLL.


--------------------
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
vl1639
Дата 25.10.2009, 21:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 55
Регистрация: 17.12.2008

Репутация: нет
Всего: нет



Приведение типов указателей выброшу.  По конкретике - в реальном варианте DLL будет совсем другой, навороченный алгоритм работы функции, к которой вызывающая программа будет обращаться многократно в течение всего времени жизни DLL и которому нужно много предистории и ее придется хранить в глобальных переменных. Результат функции мне определили (задали) как указатель на начало массива с несколькими выходными параметрами алгоритма. Насчет передачи в функцию массива с входными данными и возврата его с выходными результатами - в этом что-то есть, поговорю с тем кому эта работа нужна.  Пример выше наверно не совсем удачен, но зато общение было удачным. Спасибо за оперативные ответы.   
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Для новичков"
SnowyMetalFan
bemsPoseidon
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по Дельфи обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь
  • 90% ответов на свои вопросы можно найти в DRKB (Delphi Russian Knowledge Base) - крупнейшем в рунете сборнике материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Delphi: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0507 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.