Страница: 1 |
|
Вопрос: Передача элемента массива по ссылке
|
Добавлено: 14.05.04 11:17
|
|
Автор вопроса: Nash Bridges
|
День добрый ! Вопрос такой: как ПО ССЫЛКЕ передать в процедуру элемент массива, в котором содержатся элементы пользовательского типа UDT. Т.е. изменение в процедуре значений структуры должно приводить к изменению значений структуры - элемента массива. CopyMemory не попадаю на нужный адрес. Копирование всей структуры и затем обратное копирование не хочется делать.
Ответить
|
Номер ответа: 1 Автор ответа: LamerOnLine
ICQ: 334781088
Вопросов: 108 Ответов: 2822
|
Профиль | | #1
|
Добавлено: 14.05.04 14:59
|
Option Explicit Private Type UserType Field1 As Long Field2 As Byte Field3 As String End Type Dim MyArray(20) As UserType Private Sub Form_Load() MyArray(4).Field3 = "Old" Call MySub(MyArray(4)) MsgBox MyArray(4).Field3 End Sub Private Sub MySub(ByRef Element As UserType) Element.Field3 = "New" End Sub
Ответить
|
Номер ответа: 2 Автор ответа: Nash Bridges
Вопросов: 5 Ответов: 139
|
Профиль | | #2
|
Добавлено: 14.05.04 15:10
|
Нет. Так понятно. Но надо вот что: Option Explicit Private Type TypeTest a As Long b As Long End Type Private arTest() As TypeTest Private Sub Form_Load() ReDim arTest(1 To 2) arTest(1).a = 1 Call GetInitType MsgBox arTest(1).a ' // Должно выводиться 10. Выводится 1 End Sub Private Sub GetInitType() Dim tp As TypeTest GetType tp tp.a = 10 End Sub Private Sub GetType(ByRef tpTest As TypeTest) ' !!! Здесь надо вернуть по ссылке элемент массива, а не его копию !!! tpTest = arTest(1) ' // Копирует End Sub
Ответить
|
Номер ответа: 3 Автор ответа: LamerOnLine
ICQ: 334781088
Вопросов: 108 Ответов: 2822
|
Профиль | | #3
|
Добавлено: 14.05.04 15:50
|
Ты хочешь чтобы две переменные указывали на одно место в памяти? Это тебе не С++, не прокатит. И, если не секрет - зачем это надо? Зачем промежуточная структура нужна? Передавай сразу элемент массива по ссылке - получишь то что хочешь. Через CopyMemory можно сделать разве что нечто подобное Option Explicit Private Type TypeTest a As Long b As Long End Type Private arTest() As TypeTest Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long) Private Sub Form_Load() ReDim arTest(1 To 2) arTest(1).a = 1 Call GetInitType MsgBox arTest(1).a ' // ?????? ?????????? 10. ????????? 1 End Sub Private Sub GetInitType() Dim tp As TypeTest tp.a = 10 Call GetType(tp) End Sub Private Sub GetType(ByRef tpp As TypeTest) CopyMemory ByVal VarPtr(arTest(1)), ByVal VarPtr(tpp), Len(arTest(1)) ' !!! ????? ???? ??????? ?? ?????? ??????? ???????, ? ?? ??? ????? !!! 'tpTest = arTest(1) ' // ???????? End Sub
Ответить
|
Номер ответа: 4 Автор ответа: Nash Bridges
Вопросов: 5 Ответов: 139
|
Профиль | | #4
|
Добавлено: 14.05.04 16:01
|
1. CopyMemory ByVal VarPtr(arTest(1)), ByVal VarPtr(tpp), Len(arTest(1)) тоже самое что и CopyMemory arTest(1), tpp, Len(arTest(1)) 2. Это копирование. Оно не подходит хотя бы из-за вложенности массивов. Да и не хочется копировать. 3. Массив приватно определен в одном модуле, а используется в другом. Соответственно, заранее неизвестно с каким элементом неоходимо работать. И не получется не запросить элемент массива, не запросить весь массив. 4. Пока только одна идея работает. Это передавать весь массив по ссылке сразу во все функции, где он может понадобиться.
Ответить
|
Номер ответа: 5 Автор ответа: LamerOnLine
ICQ: 334781088
Вопросов: 108 Ответов: 2822
|
Профиль | | #5
|
Добавлено: 14.05.04 16:20
|
Так, еще раз... Зачем тебе временная структура? Неважно во скольких модулях ты хочешь использовать элемент своего приватного массива, лишь бы тип был побличный: 'Модуль 1 Option Explicit Public Type MyType Field1 As Long Field2 As Long End Type Private Massive(20) As MyType Sub main() Call mass(Massive(10)) MsgBox Massive(10).Field1 End Sub 'Модуль 2 Option Explicit Sub mass(ByRef Elem As MyType) Elem.Field1 = 123 End Sub Где тут копирование???
Ответить
|
Номер ответа: 6 Автор ответа: Nash Bridges
Вопросов: 5 Ответов: 139
|
Профиль | | #6
|
Добавлено: 14.05.04 16:29
|
Ты спросил зачем несколько функций. Я ответил, что в разных модулях. Конечно не важно что в нескольких. 'Модуль 1 Option Explicit Public Type MyType Field1 As Long Field2 As Long End Type Private Massive(20) As MyType Sub main() Call mass(Massive(10)) ' !!!!! Еще раз. Здесь неизвестен еще индекс элемента, который нужен. Поэтому нельзя передавать конкретный элемент. MsgBox Massive(10).Field1 End Sub 'Модуль 2 Option Explicit Sub mass(ByRef Elem As MyType) Elem.Field1 = 123 End Sub
Ответить
|
Номер ответа: 7 Автор ответа: LamerOnLine
ICQ: 334781088
Вопросов: 108 Ответов: 2822
|
Профиль | | #7
|
Добавлено: 14.05.04 17:13
|
Ну, если это так принципиально и никак не обойтись, то проблема. Дурной способ: Option Explicit Private Type TypeTest a As Long b As Long End Type Private arTest() As TypeTest Private Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long Private Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, lpBaseAddress As Any, lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long Private Declare Function GetCurrentProcess Lib "kernel32" () As Long Dim hProcess As Long Private Sub Form_Load() hProcess = GetCurrentProcess ReDim arTest(1 To 2) arTest(1).a = 1 Call GetInitType MsgBox arTest(1).a ' // End Sub Private Sub GetInitType() Dim tp As TypeTest Dim Address As Long Dim Value As Long GetType Address, 1 Value = 10 WriteProcessMemory hProcess, ByVal Address, Value, ByVal 4&, ByVal 0& 'записывает по адресу значение End Sub Private Sub GetType(ByRef Address, ByRef Index) Address = VarPtr(arTest(Index)) 'определяет адрес End Sub
Ответить
|
Номер ответа: 8 Автор ответа: Nash Bridges
Вопросов: 5 Ответов: 139
|
Профиль | | #8
|
Добавлено: 14.05.04 17:25
|
CopyMemory так же можно делать. Конечно, неплохо. Но неудобно так работать со структурой Тогда все преимущества их использования выпадают.
Ответить
|
Номер ответа: 10 Автор ответа: Nash Bridges
Вопросов: 5 Ответов: 139
|
Профиль | | #10
|
Добавлено: 14.05.04 17:33
|
Сложно это очень получается. Там вложенные массивы других UDT. Их тоже надо заполнять. Я так думаю, что самое простое передавать весь массив сразу. Еще наверное что то можно сделать с SafeArray.
Ответить
|
Номер ответа: 11 Автор ответа: cresta
Вопросов: 117 Ответов: 1538
|
Профиль | | #11
|
Добавлено: 14.05.04 18:20
|
Похоже, тебе надо в OLEAUT32 лезть: DECLARE FUNCTION SafeArrayGetDim LIB "OLEAUT32.DLL" ALIAS "SafeArrayGetDim" (BYVAL psa AS DWORD) AS DWORD DECLARE FUNCTION SafeArrayGetElement LIB "OLEAUT32.DLL" ALIAS "SafeArrayGetElement" (BYVAL psa AS DWORD, rgIndices AS LONG, pData AS ANY) AS LONG DECLARE FUNCTION SafeArrayGetLBound LIB "OLEAUT32.DLL" ALIAS "SafeArrayGetLBound" (BYVAL psa AS DWORD, BYVAL nDim AS WORD, lbDim AS LONG) AS LONG DECLARE FUNCTION SafeArrayGetUBound LIB "OLEAUT32.DLL" ALIAS "SafeArrayGetUBound" (BYVAL psa AS DWORD, BYVAL nDim AS WORD, ubDim AS LONG) AS LONG DECLARE FUNCTION SafeArrayRedim LIB "OLEAUT32.DLL" ALIAS "SafeArrayRedim" (BYVAL psa AS DWORD, BoundNew AS SAFEARRAYBOUND) AS LONG
Передавать в функцию указатель на массив, в функции восстанавливать LBound, UBound, и делать со своим массивом какие - либо действия
Ответить
|
Номер ответа: 12 Автор ответа: Nash Bridges
Вопросов: 5 Ответов: 139
|
Профиль | | #12
|
Добавлено: 14.05.04 19:02
|
как вариант. но там массивы надо лочить и так далее. поэтому видимо проще чем сказал - не сделать.
Ответить
|
Страница: 1 |
Поиск по форуму