Страница: 1 | 2 | 3 |
Как передать массив в DLL? В DLL есть такие ф-ция и процедура: ' поиск в массиве значения LVal, возвращает номер элемента SUB SortArrDescend (Arr() AS LONG ) EXPORT Из VB создаю массив() as Long, заполняю его Arr(i)= Clng(RND*1000) и затем вызываю ф-цию ScanArrEqu
Ну так и передай ему ссылку на массив. VB: ArrPtr=VarPtr(Array) Почему невозможна? Самый, имхо, лучший вариант: ты передаешь указатель на array(0) и длину массива в байтах, DLL создает массив такого размера и копирует в него эти байты, а потом работает как со своим. Потом возвращает либо то, что тебе нужно, либо указатель на arrayDLL(0), после чего ты можешь этот массив либо использовать, либо скопировать обратно к себе в array(0). Да я там уже был. Но это ничего не даёт, т.к. передавая в процедуру указатель на первый элемент и длину массива, не удаётся из этих данных восстановить массив внутри DLL, чтобы его отсортировать. Делал такую процедуру: А вот по поводу, чтобы длл возвращала указатель на сортированый массив - это зачем, он что переезжает куда то что ли при сортировке? Адрес в памяти ведь прежний остается, после вызова процедуры я снова освежаю листбокс и вижу в нем старый порядок массива. ByVal сразу приводит к падению IDE, неважно указатель ByVal или размер ByVal. А собирать с помощью PEEK - POKE тоже ничего не даст, в VB не соберёшь обратно... Видно передать массив функции невозможно. 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, думаю, не помешает, судя по его популярности. А если так? 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 Не есть хорошо. Надо: For FillArr1 = 0 To 1000 Step 100: Arr1(FillArr1 \ 100) = FillArr1: Next FillArr1 :D 2brevno: мысль-то хорошая, только, имхо, PB не стоит такого напряга... Ладно бы мы нашли идеальный язык программирования, на котором будем писать до самой смерти, а тут... 16-битный платный компилятор, до сих пор воняющий нафталином QBasic'а... Хотя сделать это стоит хотя бы по той причине, что мы будем иметь шанс продать производителю PB его локализацию )) Чувствую без меня эта тема увянет )) Шучу Уаааау, сколько всего сразу!!!!!!! Это всё мне??? Ну, спасибо всем! Как говорили раньше, растроган до глубины души, блин. Спасибо ещё раз всем. Буду ковырять...
Вопрос: Как передать массив
Добавлено: 23.01.04 18:55
Автор вопроса: cresta
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
ARRAY SORT Arr&(), DESCEND ' сортировка по убыванию
END SUB
retval& = SCANARREQU ( Arr(), 55) ' возвращает ноль, элемент не найден, хотя 55 заведомо в нем есть
И процедура SORTARRDESCEND Arr() тоже не срабатывает, массив остается не сортирован.
Причём и ф-ция, и процедура из среды РВ работают, тут ошибки нет.
Может, я как-то не так передаю массив в ф-цию?. Через ByVal не получается, VB ругается, что массив надо передавать по ссылке. Или может передача массива в DLL в принципе невозможна?
Ответы
Всего ответов: 32
Номер ответа: 1
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #1
Добавлено: 23.01.04 19:17
Номер ответа: 2
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #2
Добавлено: 23.01.04 20:09
Номер ответа: 3
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #3
Добавлено: 23.01.04 22:26
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
 im 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-сайт:
Профиль | | #5
Добавлено: 23.01.04 22:35
Насколько я понимаю, передавая так аргументы, ты реально передаешь указатель на ArrPtr (на указатель) и указатель на 1001 (не знаю, какого типа, наверно, Integer), а надо
Номер ответа: 6
Автор ответа:
cresta
Вопросов: 117
Ответов: 1538
Профиль | | #6
Добавлено: 23.01.04 23:46
Номер ответа: 7
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #7
Добавлено: 23.01.04 23:59
Не падай духом! Сохраняй свой массив в файл, открывай его DLLей, сортируй и сохраняй обратно. А вообще, используй QuickSort, он работает настолько быстро, что тебе и DLL не придется писать.
Номер ответа: 8
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #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-сайт:
Профиль | | #9
Добавлено: 24.01.04 00:59
Номер ответа: 10
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #10
Добавлено: 24.01.04 01:10
Номер ответа: 11
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #11
Добавлено: 24.01.04 01:12
А вообще, если ты земетил, кроме тебя уже все его начали изучать.
Номер ответа: 12
Автор ответа:
Sharp
Лидер форума
ICQ: 216865379
Вопросов: 106
Ответов: 9979
Web-сайт:
Профиль | | #12
Добавлено: 24.01.04 01:28
Номер ответа: 13
Автор ответа:
sne
Разработчик Offline Client
ICQ: 233286456
Вопросов: 34
Ответов: 5445
Web-сайт:
Профиль | | #13
Добавлено: 24.01.04 01:35
Держи руку помощи, надеюсь что не зря 20 мин. потратил, и хоть чем-то да помогу...
Код для VB:Option Explicit
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
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"
ByVal iCnt As Long) Export ' Кол-во элементов
ReDim Arr(iCnt - 1&) ' Ресайзим его
For i = 0 To iCnt - 1&
MsgBox("Получено: " & Str$(Arr(i)))
Next
Вот еще вариант... Видать почти зазря тут пол-часа сидел...
Номер ответа: 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 возвращают разные значения. Это так на заметку...