Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Power Basic

Страница: 1 | 2 | 3 |

 

  Вопрос: Как передать массив Добавлено: 23.01.04 18:55  

Автор вопроса:  cresta

Как передать массив в DLL? В DLL есть такие ф-ция и процедура:

' поиск в массиве значения LVal, возвращает номер элемента
FUNCTION ScanArrEqu (Arr() AS LONG, LVal AS LONG ) EXPORT AS LONG
    LOCAL hResult AS LONG
    ARRAY SCAN Arr&(), = LVal, TO hResult
    FUNCTION = hResult
END FUNCTION

SUB SortArrDescend (Arr() AS LONG ) EXPORT
    ARRAY SORT Arr&(), DESCEND ' сортировка по убыванию
END SUB 

Из VB создаю массив() as Long, заполняю его Arr(i)= Clng(RND*1000) и затем вызываю ф-цию ScanArrEqu
retval& = SCANARREQU ( Arr(), 55) ' возвращает ноль, элемент не найден, хотя 55 заведомо в нем есть
И процедура SORTARRDESCEND Arr() тоже не срабатывает, массив остается не сортирован.
Причём и ф-ция, и процедура из среды РВ работают, тут ошибки нет.
Может, я как-то не так передаю массив в ф-цию?. Через ByVal не получается, VB ругается, что массив надо передавать по ссылке. Или может передача массива в DLL в принципе невозможна?

Ответить

  Ответы Всего ответов: 32  

Номер ответа: 1
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #1
Добавлено: 23.01.04 19:17

Ну так и передай ему ссылку на массив.

VB: ArrPtr=VarPtr(Array)

 

Ответить

Номер ответа: 2
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #2
Добавлено: 23.01.04 20:09

Почему невозможна? Самый, имхо, лучший вариант: ты передаешь указатель на array(0) и длину массива в байтах, DLL создает массив такого размера и копирует в него эти байты, а потом работает как со своим. Потом возвращает либо то, что тебе нужно, либо указатель на arrayDLL(0), после чего ты можешь этот массив либо использовать, либо скопировать обратно к себе в array(0).

Ответить

Номер ответа: 3
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #3 Добавлено: 23.01.04 22:26

Да я там уже был. Но это ничего не даёт, т.к. передавая в процедуру указатель на первый элемент и длину массива, не удаётся  из этих данных восстановить массив внутри DLL, чтобы его отсортировать. Делал такую процедуру:
SUB SortArrDescend(ArrPointer AS LONG PTR, ArrLen AS LONG ) EXPORT
    DIM CurrentPos AS LONG
    DIM LocalArr () AS LONG
    REDIM LocalArr (1:ArrLen) AS LONG
    FOR CurrentPos = 0 TO ArrLen - 1
        LocalArr(CurrentPos)= @ArrPointer[CurrentPos]
    NEXT CurrentPos
    ARRAY SORT LocalArr&;(), DESCEND
END SUB
И когда вызываю её из VB
 ;Dim ArrPtr As Long
 ArrPtr = VarPtrArray(Arr())
 SORTARRDESCEND ArrPtr, 1001
Массив остаётся несортированым.

А вот по поводу, чтобы длл возвращала указатель на сортированый массив - это зачем, он что переезжает куда то что ли при сортировке? Адрес в памяти ведь прежний остается, после вызова процедуры я снова освежаю листбокс и вижу в нем старый порядок массива.

Ответить

Номер ответа: 4
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #4 Добавлено: 23.01.04 22:32
Может дело в том, что в ПБ указатель имеет свой тип данных PTR, и восстанавливает массив через такой тип указателя, а в ВБ его нет и приходится передавать просто лонг

Ответить

Номер ответа: 5
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #5
Добавлено: 23.01.04 22:35
SORTARRDESCEND ArrPtr, 1001
Насколько я понимаю, передавая так аргументы, ты реально передаешь указатель на ArrPtr (на указатель) и указатель на 1001 (не знаю, какого типа, наверно, Integer), а надо
SORTARRDESCEND ByVal ArrPtr, ByVal 1001&
Попробуй, должно помочь, хотя по поводу части на PB я ничего не могу сказать.
Я говорил, что функция должна возвращать указатель на свой, отсортированный массив, если она его к себе по указателю копирует и не меняет главный массив.

Ответить

Номер ответа: 6
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #6 Добавлено: 23.01.04 23:46

ByVal сразу приводит к падению IDE, неважно указатель ByVal  или размер ByVal.  А собирать с помощью PEEK - POKE тоже ничего не даст, в VB не соберёшь обратно... Видно передать массив функции невозможно.

Ответить

Номер ответа: 7
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #7
Добавлено: 23.01.04 23:59
Не падай духом! Сохраняй свой массив в файл, открывай его DLLей, сортируй и сохраняй обратно. А вообще, используй QuickSort, он работает настолько быстро, что тебе и DLL не придется писать.

Ответить

Номер ответа: 8
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #8
Добавлено: 24.01.04 00:42
Держи! Хоть и сам помучался зато знаю теперь как это делать.
===
-VB-
Private Declare Function GetArray Lib "DllArray.DLL" (MyArray As Long, Index As Integer) As Long
Private Sub Form_Load()
Dim Arr1(10) As Long
Arr1(0) = 0
For FillArr1 = 1 To 10: Arr1(FillArr1) = Arr1(FillArr1 - 1) + 100:  Next FillArr1
x = GetArray(Arr1(0), 9)
End Sub
----------------------------
-PBDLL-
Function GetArray Alias "GetArray"(MyArray As Long,Index As Integer) Export As Long
Dim xPtr As Long Pointer
xPtr = VarPtr(MyArray)
MsgBox Str$(@xPtr[Index])
End Function

Ответить

Номер ответа: 9
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #9
Добавлено: 24.01.04 00:59

CyRax, ты прирожденный хакер!

For FillArr1 = 1 To 10: Arr1(FillArr1) = Arr1(FillArr1 - 1) + 100: Next FillArr1

Я на такой код любовался минуты три. Теперь я понимаю ужас Ромы, когда я сказал ему, что программы комментировать не надо, они и так понятны. Другими словами:

if(a&&!b||c){d*=&(++e==*f++)+g++}

А все таки, чувствую, статью "Вызов WinAPI на Visual Basic" написать надо. Буду очень благодарен всем, кто предоставит мне информацию относительно передачи аргументов и указателей в PB, думаю, не помешает, судя по его популярности.

Ответить

Номер ответа: 10
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #10
Добавлено: 24.01.04 01:10

А если так?

For FillArr1 = 0 To 1000 Step 100: Arr1(FillArr1 / 100) = FillArr1: Next FillArr1

Ответить

Номер ответа: 11
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #11
Добавлено: 24.01.04 01:12
А вообще, если ты земетил, кроме тебя уже все его начали изучать.

Ответить

Номер ответа: 12
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #12
Добавлено: 24.01.04 01:28

Где-то я уже упоминал, что Обломов рядом со мной - гибрид пчелы и муравья :)

> For FillArr1 = 0 To 1000 Step 100: Arr1(FillArr1 / 100) = FillArr1: Next FillArr1

Не есть хорошо. Надо:

For FillArr1 = 0 To 1000 Step 100: Arr1(FillArr1 \ 100) = FillArr1: Next FillArr1

:D

2brevno: мысль-то хорошая, только, имхо, PB не стоит такого напряга... Ладно бы мы нашли идеальный язык программирования, на котором будем писать до самой смерти, а тут... 16-битный платный компилятор, до сих пор воняющий нафталином QBasic'а... Хотя сделать это стоит хотя бы по той причине, что мы будем иметь шанс продать производителю PB его локализацию :)))

Ответить

Номер ответа: 13
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #13
Добавлено: 24.01.04 01:35

Чувствую без меня эта тема увянет ;))) Шучу :)

Держи руку помощи, надеюсь что не зря 20 мин. потратил, и хоть чем-то да помогу...

Код для VB:

Option Explicit

 

Private Declare Sub GetArray Lib "f:\new.dll" (ByRef Destination As Long, ByVal cnt As Long)
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)

 

Private Sub Form_Load()
Dim i As Long, MyArr() As Long

ReDim MyArr(3)

For i = 0 To UBound(MyArr)
MyArr(i) = Rnd(Timer) * 100
Call MsgBox(MyArr(i))
Next

 

' Отсюда - самое главное
Dim out As Long
Call CopyMemory(out, MyArr(0), (UBound(MyArr) + 1&) * Len(MyArr(0)))

 

' Вызов нашей функции
Call GetArray(out, UBound(MyArr) + 1&)
End Sub


Код для PB:


#Compile Dll "New.dll"
#Include "Win32Api.inc"

 

Sub DoThis Alias "GetArray" (ByRef inArr As Long, _ ' Указатель на нулевой элемент массива
ByVal iCnt As Long) Export ' Кол-во элементов

 

Dim Arr() As Long ' Объявление массива
ReDim Arr(iCnt - 1&) ' Ресайзим его

 

Call MoveMemory(Arr(0), inArr, &H4 * iCnt) ' Заносим данные в массив

 

Dim i As Long ' Проверяем то - ли получили.
For i = 0 To iCnt - 1&
MsgBox("Получено: " & Str$(Arr(i)))
Next

 

' Сортировка -------------------------------

 

' Сортировка -------------------------------

 

' Как обратно вернуть массив, думаю по аналогии сообразить можно...

 

End Sub


Вот еще вариант... Видать почти зазря тут пол-часа сидел...

Ответить

Номер ответа: 14
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #14 Добавлено: 24.01.04 01:58

Уаааау, сколько всего сразу!!!!!!! Это всё мне???   Ну, спасибо всем!  Как говорили раньше, растроган до глубины души, блин. Спасибо ещё раз всем. Буду ковырять...

 

Ответить

Номер ответа: 15
Автор ответа:
 cresta



Вопросов: 117
Ответов: 1538
 Профиль | | #15 Добавлено: 24.01.04 06:42
Короче, вот что я наковырял за ночь: как предлагал Cyrax, я раньше делал, но результата не было, по его наводке стал тыкать везде msgbox  и всё прояснилось: указателем массив передать можно, он сортируется, но результатами сортировки не воспользуешься, т.к. массив при этом съезжает в сторону, и xPTR сортированного массива не совпадает с исходным... возвращать его в VB смысла нет, массив собрать нечем, поэтому добавил как Sne предложил, внутри DLL MoveMemory, стало сортировать и перемещать на место, вроде заработало, но почему-то при массивах больше 1000 элементов IDE падает, видимо MoveMemory наезжает на чужую область памяти. А до 1000 всё работает. И ещё: указатели на один и тот же массив из ПБ и через VarPtrArray изVB возвращают разные значения. Это так на заметку...

Ответить

Страница: 1 | 2 | 3 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам