![]() |
|
Модераторы: Poseidon, Snowy, bems, MetalFan |
![]()
|
|
| Maximus |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.8.2002 Репутация: нет Всего: нет |
У меня возникла такая проблема. Хорошо знаю VB, а Delphi недавно изучаю. Так вот. Мне необходимо из VB передать в DLL двумерный массив. В Dll этот массив преобразовывается по некорому алгоритму (например алгоритм взятия обратной матрицы). В DLL должна быть функция которая может в VB вернуть этот преобразованный массив.
Помогите. Время поджимает!!! Горю!!! |
|||
|
||||
| Vit |
|
|||
![]() Vitaly Nevzorov ![]() ![]() ![]() ![]() Профиль Группа: Экс. модератор Сообщений: 10964 Регистрация: 25.3.2002 Где: Chicago Репутация: 48 Всего: 207 |
Взять одной функцией, а вернуть другой не получиться. Выходов 3:
1) Если входной и выходной массивы одинаковые по структуре то функция описывается так: Procedure MyProc(var MyArr:TMyArray); Тогда выполнив процедуру у тебя результат будет в том же массиве 2) Если входной и выходной массивы разные по структуре то функция описывается так: Procedure MyProc(MyArr1:TMyArray1;var MyArr2:TMyArray2); 3) Если же надо непременно использовать разные процедуры, то тогда пиши свой ActiveX или свой класс, и зашивай его в 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 |
|||
|
||||
| Maximus |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.8.2002 Репутация: нет Всего: нет |
Ладно, начнем с простого:
вот содержание моей DLL: //------------------------------------------------------------------ library cholecky; uses SysUtils,Math; function chol (var A: array of real ;m: integer): real; stdcall; var r: integer; b: real; begin; For r:=0 to m do begin b:=b+A[r]; end; chol:=b; end; exports chol index 1; begin end. //------------------------------------------------------------------ А вот код в котором я вызываю функцию chol из cholecky.dll: //------------------------------------------------------------------ program Project1; uses Forms; {$R *.res} var u: array[0..3] of real; i: real; function chol(var A:array of real; m: integer):real ;external 'cholecky.dll' index 1; begin u[0]:=1; u[1]:=2; u[2]:=3; u[3]:=4; i:=chol(u,3); writeln (i); readln; end. //------------------------------------------------------------------ И не чего не работает. А из VB тем более!!!!!!!!!!!!!! Пишет типа: не в ту странцу памяти лезешь и т.д. и т.п. |
|||
|
||||
| Mikel |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 882 Регистрация: 30.3.2002 Где: Саратов Репутация: 1 Всего: 2 |
Возможно это поможет:
укажи в программе функцию как stdcall массив задан как статический, а в процедуре- динамический. А может это глупости. -------------------- ...so remember, it's better to burn out than to fade away |
|||
|
||||
| Maximus |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.8.2002 Репутация: нет Всего: нет |
Нарооод!
Ну есть же среди Вас настоящие профессионалы дельфийского искусства! Набросайте пару строк! Да и дело с концом! Всем будет хорошо. А то так можно до нового года обрывками фраз перебрасываться! HELP!SOS! |
|||
|
||||
| Mikel |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 882 Регистрация: 30.3.2002 Где: Саратов Репутация: 1 Всего: 2 |
Ладно, так уж и быть
uses Forms; - ты что хотел этим сказать? Что у тебя форма? А это что writeln (i); readln; ? Если ты уж так хочешь сделать из Delphi Pascal, то New->Console Application и перенеси все туда. А если по-нормальному, то оставь форму, а вместо writeln (i); readln; пиши ShowMessage(FloatToStr(i)); И все. Проблема не в DLL. -------------------- ...so remember, it's better to burn out than to fade away |
|||
|
||||
| Maximus |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.8.2002 Репутация: нет Всего: нет |
Ладно с этим я уже сам разобрался еще вчера вечером!
Теперь у меня вот такой код: Dll ------------------------------------------------------ library cholecky; uses SysUtils,Math; type TMultyDimArray = array of array of real; procedure chol (var A: TMultyDimArray; m: integer; n: integer); stdcall; var i: integer; j: integer; b: real; begin; For i:= 0 to m do begin for j:= 0 to n do begin A[i,j]:=A[i,j]*2; end; end; end; exports chol ; begin end. -------------------------------------------------------- А вот программка откудая я ее вызываю: (кстати она консольная) -------------------------------------------------------- program Project1; uses Forms; <--- Это сама делфи ставит, так что не ко мне вопросы type TMultyDimArray = array of array of real; {$R *.res} Procedure chol(var A:TMultyDimArray; m: integer; n: integer);stdcall; external 'cholecky.dll' index 1; var u: TMultyDimArray; I: integer; J: integer; otvet: real; mm: integer; nn: integer; begin mm:=4; nn:=4; SetLength(u, mm); writeln('Was'); for I := Low(u) to High(u) do begin SetLength(u[I], nn); for J := Low(u[I]) to High(u[I]) do begin u[I,J] := 3; writeln(u[I,J]); end; writeln; end; chol(u,3,3); readln; writeln('Will be'); for I := Low(u) to High(u) do begin for J := Low(u[I]) to High(u[I]) do begin writeln(u[I,J]); end; writeln; end; readln; end. ------------------------------------------ Так вот, все работает, как видите двумерный массив заполняется цифрами 3, а затем они функцией dll-ки перобразуются в 6-ки. А в VB это не работает а мне надо!! очень!! Вот код из VB --------------------------------------------------- На форме есть две кнопки Command1 и Command2 и компонент RichTextBox1 (типа мемо в дельфи). ' Самое главное это объявление ниже Private Declare Sub chol Lib "cholecky.dll" (ByRef b() As Double, ByVal m As Integer, ByVal n As Integer) Dim a() As Double Dim v As Integer Private Sub Command1_Click() ReDim a(1, 1) a(0, 0) = 1 a(0, 1) = 2 a(1, 0) = 3 a(1, 1) = 4 For i = 0 To 1 For j = 0 To 1 Text1 = Text1 & CStr(a(i, j)) & " " Next j Text1 = Text1 & vbCrLf Next i RichTextBox1.Text = Text1 End Sub Private Sub Command2_Click() chol a, 1, 1 <- А это вызов моей злосчастной функции Text1 = "New" & vbCrLf For i = 0 To 1 For j = 0 To 1 Text1 = Text1 & CStr(a(i, j)) & " " Next j Text1 = Text1 & vbCrLf Next i RichTextBox1.Text = Text1 End Sub С наилучшими пожеланиями Maximus! P.S. Спасибо за живой диалог Ж |
|||
|
||||
| Fantasist |
|
|||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: нет Всего: 41 |
Мне вообще такой подход претит. Ведь очень вероятно, что динамические массивы манипулируются VB совсем не так как в Delphi. Что надо делать - это передавать указатель. И лучше всего указатель на структуру (класс был бы еще лучше, но опять же нет гарантии одинакового создания объекта в разных языках).Либо используй Variant array - фактически будет то же самое, что и с указателем, только обрабатывать не ты будешь. А про эти динамические массивы вообще забудь, если думаешь об универсальности. Незнаю, как в VB, но в Delphi это бы выглядело примерно так:
Это, конечно, набросок, но идея понятна. Хотя все-таки надо OLE Variant array использовать , но об этом в следующий раз. -------------------- Волны гасят ветер... |
|||
|
||||
| Maximus |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.8.2002 Репутация: нет Всего: нет |
Вообщем-то суть понятна. Спасибо, но почемуто не работает
На первом же значке ^, в объявлении процедуры ....SetDynArr(arr:^TM.... пишет: " Identifier expected but '^' found ". И не компилируется! Напишите пожалуйста, как воспользоваться этим всем из Dll и из проги ее вызывающей. |
|||
|
||||
| Mikel |
|
|||
|
Опытный ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 882 Регистрация: 30.3.2002 Где: Саратов Репутация: 1 Всего: 2 |
Напиши до этого
type PMyIntDynArray=^TMyIntDynArray; А где надо ^TMyIntDynArray- замени на PMyIntDynArray -------------------- ...so remember, it's better to burn out than to fade away |
|||
|
||||
| Fantasist |
|
||||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: нет Всего: 41 |
Хм... Мне, кажется, что объяснить это тебе, для меня будет долговато. Кажется у тебя пока не хватает некоторых знаний. В общем, я тебе привел функции для работы (запись/чтение/установка размера) с придуманным на ходу мною динамическим массивом, который представляет из себя структуру содержащую три переменные: указатель на начало некоторой области памяти, и две переменные(высота и ширина, условно говоря), которые указывают как эту область понимать. Функции эти оперируют с указателем на такую структуру. Запись: ^TMyIntDynArray - это есть тип - указатель на эту структуру. Ошибка при компилировании возникает либо от моего незнания, как записать в параметре такую вещь, либо из-за ограничености компилятора. В С++ я записываю именно так. Здесь же можно переписать это в виде:
type TMyIntDynArray=record m,n:LongInt; arr:pointer; end; pMyIntDynArray=^TMyIntDynArray; И везде вместо ^TMyIntDynArray записать pMyIntDynArray. Теперь тебе надо эти функции доработать, чтобы они не глючили, переписать свою chol примерно так:
и дальше в этой функции работать с arr, в VB описать точно такую же структуру как TMyIntDynArray, и потом в функцию chol из VB передавать указатель на эту структуру. Это, на самом деле, не грамотный путь, но будет работать. Более грамотный это работать с OleVariant в Delphi есть поддержка:
и если такой variant array принадлежит к Automatation types, то поддержка есть и VB, но этого я пока не знаю. Еще однин грамотный путь - это как Vit сказал, написать COM объект. Если в VB поддержка работы с интерфейсами присутсвует, или хотя бы виртуальные таблицы там создаются точно также(это почти наверняка) и с ними можно нормально работать, то необязательно даже полностью писать ActiveX, можно просто написать интерфейсный объект, который ты запихнешь в dll и будешь сам его создавать. -------------------- Волны гасят ветер... |
||||
|
|||||
| Maximus |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.8.2002 Репутация: нет Всего: нет |
Еще не получив ответа от Fantasista, я написал программку. Но компилятор тоже ворчит!!!!
Вот код моей программки! uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Memo1: TMemo; procedure Button1Click(Sender: TObject); private { Private declarations } public { Public declarations } end; type TMyIntDynArray=record m,n:LongInt; arr:pointer; end; type PMyIntDynArray=^TMyIntDynArray; <- Написал как вы советовали! var Form1: TForm1; myarr: PMyIntDynArray; a,b: integer; implementation {$R *.dfm} { Вот здесь начинаются ваши процедуры и функции В их заголовках я изменил ^TMyIntDynArray на PMyIntDynArray } procedure SetDynArr(arr:PMyIntDynArray;x,y:integer;Value:integer); var p:^LongInt; begin if (x>arr^.m) or (y>arr^.n) then exit; p:=arr^.arr; inc(p,x*arr^.m+y); p^:=Value; end; function GetDynArr(arr:PMyIntDynArray;x,y:integer):integer; var p:^LongInt; begin if (x>arr^.m) or (y>arr^.n) then exit; p:=arr^.arr; inc(p,x*arr^.m+y); Result:=p^; end; procedure SetMyDynArraySize(arr:PMyIntDynArray;m,n:integer); begin GetMem(arr^.arr,m*n); FreeMem(arr^.arr,Arr^.m*Arr^.n); end; {Здесь заканчивается ваш код и начинается мой} { На форме находится кнопка и мемо. После нажатия на кнопку, хотел что бы в Memo1 у меня напечаталось содержимое myarr массива, который я объявляю тоже как PMyIntDynArray в глобальном VAR (см. выше.) } procedure TForm1.Button1Click(Sender: TObject); var j,i: integer; begin SetMyDynArraySize(myarr,3,3); <- Как я понял это выделение памяти под массив. b:=3; for i:= 0 to 3 do begin for j:= 0 to 3 do begin SetDynArr(myarr,i,j,b); <- Задаю значения элементов массива. a:=getdynarr(myarr,i,j); <- Здесь чтобы проверить предыдущую операцию извлекаю из массива значение элемента. memo1.Lines.Add(floattostr(a)); <-Это все оформление. end; end; end; end. |
|||
|
||||
| Fantasist |
|
||||||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: нет Всего: 41 |
Я же написал, что эти функции доработать надо. Я их написал только как демонстрацию идеи, а не как рабочий код. Тут, кстати, у меня не так:
А вот так:
Но и это не правильно потому что надо так:
И опять же это не совсем верно, потому как вначале при не инициализированном массиве, может случиться, будет пытаться освободиться память, которая не занята, или занята не тобой. Что касается вашего кода, то неплохо бы написать, что за ошибка у вас, иначе тяжело ответить. Да и может быть вы сами можете эту ошибку выявить и исправить? -------------------- Волны гасят ветер... |
||||||
|
|||||||
| Maximus |
|
|||
|
Новичок Профиль Группа: Участник Сообщений: 10 Регистрация: 13.8.2002 Репутация: нет Всего: нет |
Вобщем-то все понятно, и почему на 4 умножено в тоже понятно
....4*Arr^.m*Arr^.n.... ( т.к. под значение типа Integer выделяется 4 байта). Немного не понял фразу: "при не инициализированном массиве, может случиться, будет пытаться освободиться память, которая не занята, или занята не тобой". И тогда интересно все-таки, с чего начать определние памяти под массив, если я не знаю занята ли эта область памяти кем-то или чем-то. А вот компилятор выдает следующее ругательство: " Project Project1.exe raised exception class EAccessViolation with message 'Access violation at address 0044FCB9 in module 'PROJECT1.EXE'. Read of address FFFFFFFF'. Process stopped. Use Step or Run to continue. " |
|||
|
||||
| Fantasist |
|
||||||
|
Лентяй ![]() ![]() ![]() Профиль Группа: Участник Клуба Сообщений: 1517 Регистрация: 24.3.2002 Репутация: нет Всего: 41 |
А это на твое усмотрение. Например, можно сделать так:
Но тогда надо точно быть уверенным, что новый экземпляр TMyIntDynArray будет иметь значение для nil для члена arr.
Это выдает не компилятор, а программа. Это так называемая run-time ошибка. EAccessViolation возникает при обращении к памяти, с которой ты не можешь работать. Бери и смотри под отладчиком. -------------------- Волны гасят ветер... |
||||||
|
|||||||
![]()
|
| Правила форума "Delphi: Общие вопросы" | |
|
|
Запрещается! 1. Публиковать ссылки на вскрытые компоненты 2. Обсуждать взлом компонентов и делиться вскрытыми компонентами
Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Snowy, MetalFan, bems, Poseidon, Rrader. |
| 0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей) | |
| 0 Пользователей: | |
| « Предыдущая тема | Delphi: Общие вопросы | Следующая тема » |
|
|
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности Powered by Invision Power Board(R) 1.3 © 2003 IPS, Inc. |