Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 |

 

  Вопрос: Передача элемента массива по ссылке Добавлено: 14.05.04 11:17  

Автор вопроса:  Nash Bridges

День добрый !

Вопрос такой: как ПО ССЫЛКЕ передать в процедуру элемент массива, в котором содержатся элементы пользовательского типа UDT. Т.е. изменение в процедуре значений структуры должно приводить к изменению значений структуры - элемента массива.

CopyMemory не попадаю на нужный адрес. Копирование всей структуры и затем обратное копирование не хочется делать.

Ответить

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

Номер ответа: 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 так же можно делать.

Конечно, неплохо. Но неудобно так работать со структурой :)

Тогда все преимущества их использования выпадают.

Ответить

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



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #9 Добавлено: 14.05.04 17:28

Вообще, конечно, можно и проще. Запомнить адрес первого элемента, а затем вычислять последующие. Они фиксированной длины. Меньше кода и пересылок.

Ответить

Номер ответа: 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 |

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



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