Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 29.01.2012, 20:20   #1
alexdelphi
Пользователь
 
Регистрация: 24.08.2011
Сообщений: 40
Вопрос странный результат функций из DLL

Решил изучить механизм создания/подключения DLL. Написал 2 небольших функции, которые считают, соответственно, количество сочетаний из n по k и на этой основе вычисляют биномиальные коэффициенты для выражения (x + y)^n при заданном n.
Сделал две версии использования функций:
1) DLLIMPRT выключен - реализация функций берется из файла с основной программой;
2) DLLIMPRT включен - реализация берется из DLL.
Далее идет код основной программы и код DLL:
Код:
{$APPTYPE CONSOLE}
const
  maxpower = 100;
type
  vector = array [0..maxpower - 1] of int64;
{$DEFINE DLLIMPRT}
{$IFDEF DLLIMPRT}
function cmb(const n,k: int64):int64; stdcall; external 'combine.dll';
function binom(pow: word):vector; stdcall; external 'combine.dll';
{$ELSE}
function cmb(const n,k: int64):int64;
  var
    i: integer;
    pr: int64;
  begin
    pr := 1;
    for i := 1 to k do
      pr := (pr * (n - i + 1)) div i; 
    cmb := pr;
  end;
function binom(pow: word):vector;
  var
    i: integer;
  begin
    for i := 0 to pow do
      binom[i] := cmb(pow,i);
  end;
{$ENDIF}
var fac: vector; i,n: integer;
begin
  readln(n);
  write('Cmb: ');
  for i := 0 to n do
    write(cmb(n,i),' ');
  writeln;
  write('Fac: ');
  fac := binom(n);
  for i := 0 to n do
    write(fac[i],' ');
  readln
end.
Код:
library combine;
const
  max_power = 100;
type
  base_int_type = int64;
  vector = array [0 .. max_power - 1] of base_int_type; 
function cmb(const n, k: base_int_type): base_int_type; stdcall;
  var
    i: integer;
    pr: base_int_type;
  begin
    pr := 1;
    for i := 1 to k do
      pr := (pr * (n - i + 1)) div i; 
    cmb := pr;
  end;
function binom(pow: word): vector; stdcall;
  var
    i: integer;
  begin
    for i := 0 to pow do
      binom[i] := cmb(pow,i);
  end;
exports
  cmb,
  binom;
begin

end.
Первая функция работает всегда правильно, для второй - первый результат всегда 0:

Код:
6
Cmb: 1 6 15 20 15 6 1
Fac: 0 6 15 20 15 6 1
Этот странный глюк с функцией binom происходит только при ее вызове из DLL, в остальных случаях 2 строки с результатами совпадают.
Кто объяснит, в чем дело?
Это один из моих первых опытов создания DLL и - такой косяк...
Примечание: при подключении обычного unit'a с функциями все работало без вопросов.
Примечание 2: использую RAD Studio 2010.

Последний раз редактировалось alexdelphi; 29.01.2012 в 20:24.
alexdelphi вне форума Ответить с цитированием
Старый 29.01.2012, 20:32   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Проверил на Delphi 6
Цитата:
6
Cmb: 1 6 15 20 15 6 1
Fac: 1 6 15 20 15 6 1
P.S. Впрочем DXE ведет себья так же.
I'm learning to live...

Последний раз редактировалось Stilet; 29.01.2012 в 20:42.
Stilet вне форума Ответить с цитированием
Старый 29.01.2012, 20:38   #3
alexdelphi
Пользователь
 
Регистрация: 24.08.2011
Сообщений: 40
По умолчанию

Со включенным DLLIMPRT?
alexdelphi вне форума Ответить с цитированием
Старый 29.01.2012, 20:45   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Я твой код один-в-один скопипастил.
Впрочем перепроверил еще раз радикальнее:
Код:
program Project1;

{$APPTYPE CONSOLE}

const
  maxpower = 100;
type
  vector = array [0..maxpower - 1] of int64;

function cmb(const n,k: int64):int64; stdcall; external 'combine.dll';
function binom(pow: word):vector; stdcall; external 'combine.dll';

var fac: vector; i,n: integer;
begin
  readln(n);
  write('Cmb: ');
  for i := 0 to n do
    write(cmb(n,i),' ');
  writeln;
  write('Fac: ');
  fac := binom(n);
  for i := 0 to n do
    write(fac[i],' ');
  readln
end.
Цитата:
6
Cmb: 1 6 15 20 15 6 1
Fac: 1 6 15 20 15 6 1
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 29.01.2012, 20:47   #5
alexdelphi
Пользователь
 
Регистрация: 24.08.2011
Сообщений: 40
По умолчанию

Спасибо... попробую взять Delphi 7
alexdelphi вне форума Ответить с цитированием
Старый 29.01.2012, 21:11   #6
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

в Делфи 20хх импорт директив осуществляется через окно свойств проекта. Ctrl+Shift+F11. Delphi Compiler -> Conditional Defines

P.S. И ничего брать не нужно, просто более детально изучить вопрос.
"ковыряю изнутри" (с)
3D Hunter вне форума Ответить с цитированием
Старый 29.01.2012, 21:20   #7
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,097
По умолчанию

Цитата:
3D Hunter
Поясни пож. что ты имеешь ввиду? Причем тут директивы?
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 29.01.2012, 21:36   #8
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Может где старый вариант DLL валяется? И именно он используется?

В самом коде ошибок нет, от версии Delphi это точно не может зависеть.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 29.01.2012, 22:00   #9
3D Hunter
Сумрачная тень
Форумчанин
 
Аватар для 3D Hunter
 
Регистрация: 05.03.2009
Сообщений: 689
По умолчанию

Писал я недавно проект, в котором модуль аппаратной защиты лицензии использовал разные директивы. В зависимости от сочетания директив задействовались те или иные возможности (генерация ключа, шифрование/расшифрование и проверка ключа, поиск всех hwid и построение списка и т.п.). Так вот, по моим наблюдениям и результаттам тестирования директива $define, объявленная в dpr-файле или где-лbбо в коде, не работает. Но если объявить ее в опциях проекта, то действие от нее включается.
З.Ы. в Д7 и более ранних можно было просто указать в проекте директиву. А в новых версиях, видимо, уже нельзя.
директивы при том, что ТС их использует для переключения в коде при компиляции: либо модуль, либо длл. Ошибка скорее в том, что нужно директиву указать так, как я написал. В противном случае имеется неявный конфликт имен функций. Если в чем не прав, поправьте меня и мои мысли.
"ковыряю изнутри" (с)

Последний раз редактировалось 3D Hunter; 29.01.2012 в 22:05.
3D Hunter вне форума Ответить с цитированием
Старый 29.01.2012, 22:03   #10
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Директива действует от момента объявления и ниже (т.е. директива в dpr файле не влияет на модули - поэтому и используют {$I defines.inc}). Директива в опциях проекта работает глобально.

Как несложно увидеть: в этом случае - без разницы.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Странный результат. Демик Помощь студентам 1 21.10.2011 21:06
Использование функций в C++ из DLL. VintProg Общие вопросы C/C++ 5 04.09.2011 03:02
Инициализация мыши странный результат X@OC Общие вопросы C/C++ 1 13.04.2011 19:02
Ошибка при выхове функций Bass.dll из другой DLL SalasAndriy Общие вопросы Delphi 7 21.10.2009 23:36
что за странный результат? marina15056 Общие вопросы Delphi 18 03.10.2009 22:09