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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Помощь по работе с DLL, Передать и вернуть двумерный массив 
:(
    Опции темы
Maximus
Дата 22.8.2002, 03:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Народ!
Я конечно понимаю, что вы гуру в своем деле, а может просто повыпендриваться на форум пришли, хотя вроде бы не похоже. Но тем не менее. Вот уже как две недели я чувствую себя пятилетним пареньком перед которым поставили вареньице на самую высокую точку кухни, и хочется, и вот вроде бы оно рядом, и не как не достать.!!!!
Когда я решил пойти на форум мне мои собратья по счастливой и несчастной моей жизни предостерегли, что на форумах ты ответа не найдешь! Что мол, там тебя попинают справа налево да ты и сам выкатишься от туда, как картофелина из кухонного комбайна!
Когда же мне посыпалось столько ответов я был просто рад, по человечески рад!
Но вот, как я уже заметил, прошло почти две недели, а результата нет.  Если бы советы были тупыми, то все понятно. Но тут все ответы к месту, и в тему. И я вижу, что скоро вот-вот и наступит день счастливого прозрения. Но он не наступает. А вы ребята по-русски говоря мудитесь. Так бы и сказали сразу, вроде того, что ты парень тупой, и далек ты от цели, и помогать тебе мы не будем. Но нет, тут идет тонкая психологическая атака, или же лень общечеловеческого характера! В другое время я бы наоборот сказал всем Вам спасибо, что не даете сразу результата, а заставляете мой неугомонный мозг развиваться по Дарвину. Но сейчас я в другой ситуации, я сгораю, мне надо это сделать. Поймите, отругайте и пожалейте меня пожалуйста братья по разуму!!!!!

С уважением ко всем форум-людям Maximus.
PM MAIL   Вверх
Vit
Дата 22.8.2002, 04:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Vitaly Nevzorov
****


Профиль
Группа: Экс. модератор
Сообщений: 10964
Регистрация: 25.3.2002
Где: Chicago

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



Ребята, я смотрю на эти рассуждения и мне всё больше и больше кажеться что это тупиковый вариант, просто детали реализации массивов от языка к языку разные, тем более двумерных массивов. Я предлагаю идти другим путём - выделить необходимый кусок памяти, сделать процедуры для перевода массива в память и обратно, а в DLL и обратно передавать только адрес на этот участок памяти и его размер - так работают все API, так оно будет работать в любой среде, главное чтобы процедуры трансформации данных были написанны правильно и делали тождественные преобразования и в DLL и в приложении... только не надо напрямую массив считать куском памяти, вряд ли это будет всегда стабильно работать.


--------------------
With the best wishes, Vit
I have done so much with so little for so long that I am now qualified to do anything with nothing
Самый большой Delphi FAQ на русском языке здесь: www.drkb.ru
PM MAIL WWW ICQ   Вверх
Fantasist
Дата 22.8.2002, 12:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


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

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



Цитата(Vit @ 21.8.2002, 21:30)
Ребята, я смотрю на эти рассуждения и мне всё больше и больше кажеться что это тупиковый вариант, просто детали реализации массивов от языка к языку разные, тем более двумерных массивов. Я предлагаю идти другим путём - выделить необходимый кусок памяти, сделать процедуры для перевода массива в память и обратно, а в DLL и обратно передавать только адрес на этот участок памяти и его размер - так работают все API, так оно будет работать в любой среде, главное чтобы процедуры трансформации данных были написанны правильно и делали тождественные преобразования и в DLL и в приложении...

Ну это не сильно другой путь. Я предлагаю реализовать процедуры чтения/записи, а ты процедуры перевода туда/обратно. Сказать что лучше на мой взгляд проблематично.

Цитата
только не надо напрямую массив считать куском памяти, вряд ли это будет всегда стабильно работать.


А вот это не понял.


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


Лентяй
***


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

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



To Maximus: Отлично! Замечательно! Очень красочно написанно! Это мне нравиться! Честно.

Конечно, ты прав. Извиняюсь и постораюсь исправиться. Просто я надеялся, что ты все-таки сам возмешся, посидишь над отладчиком, и все в конце концов сделаешь. Я напишу тебе код для Делфи, а ты, его внимательно изучешь и сделаешь точно такой же в VB.


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Fantasist
Дата 22.8.2002, 14:31 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


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

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



Вот это то, что тебе надо реализовать в VB. Структура для хранения массива, и класс-обертка для работы с ним. Дело в том, что VB я знаю смутно, но для тебя недолжно быть проблемы реализовать это там. Я его более менее отладил - работает.

Примичание: LongInt имеет размер 4 байта, как и указатель

Код


 TMyIntDynArray_Struct=record
    m,n:LongInt;
    arr:pointer;
 end;

 pMyIntDynArray_Struct=^TMyIntDynArray_Struct;

 TMyIntDynArray=class
 protected
   fArray:pMyIntDynArray_Struct;
 public
   constructor Create(m,n:LongInt);
   procedure SetValue(m,n,Value:LongInt);
   function GetValue(m,n:LongInt):LongInt;
   procedure SetSize(m,n:LongInt);
   procedure DestroyArray;
   function GetStructPointer:pMyIntDynArray_Struct;
   procedure SetStructPointer(p:pMyIntDynArray_Struct);
   function m:LongInt;
   function n:LongInt;
 end;

implementation

procedure TMyIntDynArray.SetValue(m,n,Value:LongInt);
var
p:^LongInt;
begin
if (m>=fArray^.m) or (n>=fArray^.n) or (m<0) or (n<0) or (fArray^.arr=nil) then
  exit;
p:=fArray^.arr;
inc(p,m*fArray^.n+n);
p^:=Value;
end;

function TMyIntDynArray.GetValue(m,n:LongInt):LongInt;
var
p:^LongInt;
begin
Result:=0;
if (m>=fArray^.m) or (n>=fArray^.n)  or (m<0) or (n<0) or (fArray^.arr=nil) then
  exit;
p:=fArray^.arr;
inc(p,m*fArray^.n+n);
Result:=p^;
end;

procedure TMyIntDynArray.SetSize(m,n:LongInt);
begin
if fArray^.arr<>nil then
  FreeMem(fArray^.arr,4*fArray^.m*fArray^.n);
fArray^.m:=m;
fArray^.n:=n;
GetMem(fArray^.arr,4*m*n);
end;

constructor TMyIntDynArray.Create(m, n: Integer);
begin
new(fArray);
fArray^.arr:=nil;
SetSize(m,n);
end;

procedure TMyIntDynArray.DestroyArray;
begin
if fArray^.arr<>nil then
  FreeMem(fArray^.arr,4*fArray^.m*fArray^.n);
dispose(fArray);
end;

function TMyIntDynArray.GetStructPointer: pMyIntDynArray_Struct;
begin
 Result:=fArray;
end;

procedure TMyIntDynArray.SetStructPointer(p: pMyIntDynArray_Struct);
begin
 DestroyArray;
 fArray:=p;
end;

function TMyIntDynArray.m: LongInt;
begin
 Result:=fArray.m;
end;

function TMyIntDynArray.n: LongInt;
begin
 Result:=fArray.n;
end;


А вот твоя процедура chol:
Код

procedure chol(pMyArray:LongInt);
var
 i: integer;
 j: integer;
 tmpArr:TMyIntDynArray;
begin
 tmpArr:=TMyIntDynArray.Create(0,0); // временный класс-обертка
 tmpArr.SetStructPointer(pMyIntDynArray_Struct(pMyArray));   //  задаем указатель на данные
 For i:=0 to tmpArr.m-1 do
   for j:=0 to tmpArr.n-1 do
     tmpArr.SetValue(i,j,3);
 tmpArr.Free;
end;


В нее передается указатель на TMyIntDynArray_Struct, но что-бы не было никаких вопросов по поводу типов, этот указатель передается как 4-х байтное целое.

 А вот как ее надо вызывать:
Код

var
 a:TMyIntDynArray; //переменная класса-обертки

begin
// создаешь объект класса
 a:=TMyIntDynArray.Create(5,4);
 
// что-то делаешь

chol(LongInt(a.GetStructPointer));  //ВЫЗОВ

//eще что-то делаешь

// незабудь освободить память
 a.DestroyArray;
// и удалить объект
 a.Free;
end;


Тут, конечно, ошибки никак не обрабатываются. У меня кое-где есть проверки на допустимые значения, но по ним происходит только выход из процедуры, и никак не узнаешь в чем ошибка. Но это потом...


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Maximus
Дата 27.8.2002, 17:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Все понял! Все усвоил! Большое спасибо! Сижу перевариваю. С бейсиком все намого сложнее, либо тоже не хватает знаний. Но если разберусь то выложу здесь. Если кому интересно дальнейшее развитие событий этого forum-сериала то приходите. Я думаю не раньше чем через недельку.

Отдельное спасибо Fantasist'у, за то что внял мой мольбы и дал мне священный код.

Удачи. Maximus.
PM MAIL   Вверх
Maximus
Дата 1.9.2002, 02:16 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Привет всем, кто следил за этой темой.
Наконец-то я разобрался во всех животрепещущих проблемах данной темы и облазив добрую часть интернета, все же нашел решение. Все народ вот Вам на суд исходник Dll-ки, написанной на Delphi и исходник VB-программки, которая работает с этой Dll-кой. Хочу сразу предупредить, что реализацию придумал не я. В общем на http://ourworld.compuserve.com/homepages/JDebord/tpmath.htm я нашел набор математических функций и процедур. К этому пакету прикладывался код Dll-дельфи для обмена данными с VBA-Приложениями (в часности там все экспорт функции были для работы с Excel ). Многое урезав, я выкладываю вас исходник Dll-ки работающий с массивами типа Variant. Кому надо полный код могут сходить по указанному выше урлу, либо написать мне на [email protected].

А вот и код:

Dll:

// ****************************************

library DelToBasic;

uses
 SysUtils,
 Classes,
 ComObj,
 Variants,
 Windows;

const
 MAX_FLT = 16382;
 MAX_VEC = 16382;  { Максимальное кол-во строк и столбцов}

type
 Float = Double;

 TVector     = array[0..MAX_FLT] of Float;
 PVector     = ^TVector;

 TMatrix     = array[0..MAX_VEC] of PVector;
 PMatrix     = ^TMatrix;

procedure DimMatrix(var A : PMatrix; Ubound1, Ubound2 : Integer);
 var
   I, J : Integer;
   RowSize : Word;
 begin
   if (Ubound1 < 0) or (Ubound1 > MAX_VEC) or
   (Ubound2 < 0) or (Ubound2 > MAX_FLT) then
     begin
       A := nil;
       Exit;
     end;

   { Выделяем память, елси не хватило, то выход }
   GetMem(A, Succ(Ubound1) * SizeOf(PVector));
   if A = nil then Exit;

   { Кол-во ячеек памяти на столбец }
   RowSize := Succ(Ubound2) * SizeOf(Float);

   { Кол-во ячеек памяти на всю матрицу }
   for I := 0 to Ubound1 do
     begin
       GetMem(A^[I], RowSize);
       if A^[I] = nil then
         begin
           A := nil;
           Exit;
         end;
     end;

   { Инициализация матрицы }
   for I := 0 to Ubound1 do
     for J := 0 to Ubound2 do
       A^[I]^[J] := 0.0;
end;


function GetBasicData(var V: Variant; var A: PMatrix;
                     var Rows, Cols: integer): boolean;
{
Это главная функция, она переносит из бейсиковского массива значения элементов в массив типа PMatrix
}
var
 NewV                  : Variant;
 i, j                  : integer;
 NoErrors              : boolean;
begin
  NoErrors := TRUE;

  try
     Rows := VarArrayHighBound(V, 1);
     Cols := VarArrayHighBound(V, 2);
     DimMatrix(A, Rows, Cols);
     for i := 0 to Rows do for j := 0 to Cols do
         if varType(V[i, j]) = varDouble then
           A^[i]^[j] := V[i, j]
         else
           NoErrors := FALSE;
   except on E: Exception do
       NoErrors := FALSE;
   end;
   result := NoErrors;
end;


procedure PMatrixToV(A: PMatrix; var V: Variant; Rows, Cols: integer);
{
Это функция переносит значения элементов массива PMatrix
из Delphi обратно в Basic.
}
var
 i, j                  : integer;
begin
 for i := 0 to Rows do
   for j := 0 to Cols do
     V[i, j] := A^[i]^[j]
end;

procedure DelMatrix(var A : PMatrix; Ubound1, Ubound2 : Integer);
{
Процедура освобождает память выделенную
под временную матрицу, функцией DimMatrix
}
 var
   I : Integer;
   RowSize : Word;
 begin
   if A <> nil then
     begin
       RowSize := Succ(Ubound2) * SizeOf(Float);
       for I := Ubound1 downto 0 do
         FreeMem(A^[I], RowSize);
       FreeMem(A, Succ(Ubound1) * SizeOf(PVector));
       A := nil;
     end;
 end;


{
А это экспортируемая функция. Ее суть - все элмента входящего массива увеличивает в двое.
}

function chol(var V: Variant): Variant; stdcall;
var
   A    : PMatrix;
   rows : integer;
   cols : integer;
   i,j  : integer;
begin

   if GetBasicData(V,A,rows,cols) then

   for i := 0 to Rows do
       begin
       for j := 0 to Cols do
           begin
               A^[i]^[j] :=A^[i]^[j]*2;
           end;
       end;
    PMatrixToV(A,V,rows,cols);
    Result := V;
    DelMatrix(A, Rows, Rows);
end;


exports
   chol;

begin
end.

// ****************************************

А вот и вызывающая программка на бейсике:


' ****************************************

' Бросьте на форму одну кнопку и один RichTextBox1

Private Declare Function chol Lib _
  "DelToBasic.dll" (ByRef Matrix As Variant) As Variant
' Обратите внимание на объявление внешней функции
' она полностью под властью  Variant - без этого работать не будет!

Dim b() As Double ' создаем динамический массив
' ну это так, чтобы вы видели, что массив может быть
'  определен и как динамический.

Private Sub Command1_Click()
Dim c As String

ReDim b(2, 2) As Double ' определяем размерности динамического массива b()


' В общем-то тут в основном оформление, но
   
   c = ""
   For i = 0 To 2
       For j = 0 To 2
           b(i, j) = 3  ' здесь заносим в массив b() значения элементов
           c = c & " " & CStr(b(i, j))
       Next j
       c = c & vbCrLf
   Next i
   
   c = c & vbCrLf
   
   result = chol(b)  ' Вызываем нашу функцию, которая должна увеличить значения
                     ' элементов массива b() в два раза
   For i = 0 To 2
       For j = 0 To 2
           c = c & " " & CStr(result(i, j))
       Next j
       c = c & vbCrLf
   Next i

   RichTextBox1.Text = c  ' Выводим на RichTextBox1
End Sub


' ****************************************

Удачи всем. Maximus.
PM MAIL   Вверх
Fantasist
Дата 1.9.2002, 02:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Лентяй
***


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

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



Ха! Бэйсик определяет динамический массив как OleVariant! Кто бы мог подумать. Я, кстати, тоже предлагал использовать Variant, но Maximus вроде как этот вариант изначально проигнорировал.
 Непонятно, зачем в выше приведенном коде делается перевод из Variant в PMatrix, а потом обратно. Delphi очень неплохо поддерживает работу с Variant. Да и реализация динамического массив на основе TMatrix/PMatrix хуже чем та, которую предложил я.


--------------------
Волны гасят ветер...
PM MAIL   Вверх
Илья
Дата 8.7.2003, 23:36 (ссылка)    |    (голосов: 0) Загрузка ... Загрузка ... Быстрая цитата Цитата


Unregistered











Народ помогите с такой проблемой. Вообщем задали написать прогу на летней практике, прога состоит из 2х частей самой проги и DLL ки. Суть в том что когда я в DLL пишу процедуру и указываю массив например как A: array of integer, а затем с помошью 2х циклов присваиваю этому массиву переменные например I,j т.е A[i,j]:=.... компилятор матюгается и пишет Array type of reqired т.е хочет чтоб я переопределил тип массива. Но как ему обьяснить что массив 2х мерный. Заранее спасибо
  Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Delphi: Общие вопросы"
SnowyMetalFan
bemsPoseidon
Rrader

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

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

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

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


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

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


 




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


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

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