?: Массив нулевой длины
От: Аноним  
Дата: 06.05.04 11:01
Оценка:
Требуется создать в Visual Basic массив нулевой длины,
чтобы lbound=0,ubound=-1
Redim a(0 to -1) дает ошибку
Может, кто-нибудь посоветует, как это сделать или как
это обойти?
Re: ?: Массив нулевой длины
От: black hermit Россия  
Дата: 06.05.04 11:10
Оценка:
Здравствуйте, <Аноним>, Вы писали:

А>Требуется создать в Visual Basic массив нулевой длины,

А>чтобы lbound=0,ubound=-1
А>Redim a(0 to -1) дает ошибку
А>Может, кто-нибудь посоветует, как это сделать или как
А>это обойти?
Правильно дает!

Это вааще где такое понадобиться может????????
... << RSDN@Home 1.1.3 stable >>
The darkness around me
Shores of solar sea
Oh how i wish to go down with the sun....
Re: Варианты реализации
От: Vi2 Удмуртия http://www.adem.ru
Дата: 06.05.04 11:33
Оценка: 11 (2)
Здравствуйте, Аноним, Вы писали:

А>Требуется создать в Visual Basic массив нулевой длины, чтобы lbound=0,ubound=-1
А>Redim a(0 to -1) дает ошибку
А>Может, кто-нибудь посоветует, как это сделать или как это обойти?

Есть несколько способов.
1. Использование Array() и варианта

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
  (Destination As Any, Source As Any, ByVal Length As Long)

Dim v, code As VbVarType
Dim l() As Long
  
  v = Array()
  code = vbArray Or vbLong
  CopyMemory v, code, Len(code)
  l = v


2. Использование SafeArrayCreate/SafeArrayCreateVector

Private Declare Function saCreateV Lib "oleaut32" Alias "SafeArrayCreateVector" _
  (ByVal vt As VbVarType, ByVal lLbound As Long, ByVal cElements As Long) As Long()

Dim l() As Long
  l = saCreateV(vbLong, 0, 0)


Private Type SAFEARRAYBOUND
   cElements As Long
   lLbound As Long
End Type

Private Declare Function saCreate Lib "oleaut32" Alias "SafeArrayCreate" _
  (ByVal vt As VbVarType, ByVal cDims As Long, rgsabound As SAFEARRAYBOUND) As Long()

Dim b As SAFEARRAYBOUND, l() As Long
  l = saCreate(vbLong, 1, b)
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[2]: Варианты реализации
От: Аноним  
Дата: 06.05.04 13:14
Оценка:
Здравствуйте, уважаемый Vi2,
подскажите как определить размерность массива?
Т.е. массив с одним и тем же именем может быть одно и двухмерным.
Как программно это отследить?
Re[3]: Варианты реализации
От: Vi2 Удмуртия http://www.adem.ru
Дата: 06.05.04 14:07
Оценка:
Здравствуйте, Аноним, Вы писали:

А>подскажите как определить размерность массива? Т.е. массив с одним и тем же именем может быть одно и двухмерным.
А>Как программно это отследить?

А цель этих манипуляций? Просто получить это число?
1. Через обработку ошибок. Допустим, таким образом
  On Error Resume Next

  For i = 1 To 20
    If UBound(a, i + 1) * 0 <> 0 Then
      Exit For
    End If
  Next i
  Debug.Print i


2. Используя SafeArrayGetDim. Однако эта функция использует один уровень косвенности при передаче массива, что VB не позволяет. Т.е. ByVal arr() As Any не допускается VB. *** Может быть плохо работать с масивом строк из-за ненужного копирования.

Private Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (arr() As Any) As Long
Private Declare Sub CopyMemoryX Lib "kernel32" Alias "RtlMoveMemory" _
    (ByVal Destination As Any, ByVal Source As Any, ByVal Length As Long)
Private Declare Function saGetDim Lib "oleaut32" Alias "SafeArrayGetDim" (ByVal sa As Long) As Integer

Function ArrayByVal(arr() As Long) As Long
  CopyMemoryX VarPtr(ArrayByVal), ArrPtr(arr), 4
End Function

Dim a(2, 2, 4) As Long, i As Long
  i = saGetDim(ArrayByVal(a))
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[4]: Варианты реализации
От: Аноним  
Дата: 06.05.04 14:51
Оценка:
Vi2, благодарю

Vi2>А цель этих манипуляций? Просто получить это число?


массив передается процедуре As Variant и может быть одно или двухмерным.

Предполагал, что существует встроенная возможность, получается ее нет.

Первый вариант понятен, второй, признаться и пробовать не стал.
Например не понятно почему в

CopyMemoryX VarPtr(ArrayByVal), ArrPtr(arr), 4

одна и та же функция вызывается по имени и по пвесдониму
Re[5]: Получение размерности
От: Vi2 Удмуртия http://www.adem.ru
Дата: 07.05.04 03:43
Оценка: 10 (1)
Здравствуйте, Аноним, Вы писали:

А>массив передается процедуре As Variant и может быть одно или двухмерным.

Тогда есть еще и такая возможность №3:
Function GetDims(v) As Integer
  Dim lp As Long, code As VbVarType
  
  CopyMemory code, v, Len(code)
  If code And vbArray Then ' это массив?
    ' взять адрес структуры SAFEARRAY, в которой хранится размерность
    CopyMemory lp, ByVal VarPtr(v) + 8, 4

'    If code And &H4000 Then ' есть лишняя косвенность?
'      CopyMemory lp, ByVal lp, 4
'    End If
    
    CopyMemory GetDims, ByVal lp, Len(GetDims)
  End If
End Function

  Dim v
  ReDim v(2, 3, 4) As Long
  Debug.Print GetDims(v)

  Debug.Print GetDims(Array(1, 2, 3))

А>Предполагал, что существует встроенная возможность, получается ее нет.

Так она бесполезна для самого языка. Даже если ты определил размерность, использовать в программе не сможешь: нет способа вызвать такой элемент массива динамически. Единственное исключение — передавать эту информацию дальше кому-нибудь.

А>CopyMemoryX VarPtr(ArrayByVal), ArrPtr(arr), 4

А>одна и та же функция вызывается по имени и по псевдониму

Есть такое в VB — можно определить несколько вариантов использования одной и той же внешней функции. Например:
Private Declare Function ArrPtr Lib "msvbvm60" Alias "VarPtr" (arr() As Any) As Long
Private Declare Function VarPtr Lib "msvbvm60" Alias "VarPtr" (arr As Any) As Long
Реальная функция VarPtr в библиотеке msvbvm60.dll используется под именем VarPtr и ArrPtr, но получает разные параметры на входе. Почему? Потому что если мы напишем VarPtr(arr), то получим сообщение об ошибке несоответствия типа. Приходится обходить контроль вручную через уточнение параметра.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! © КВН НГУ
Re[6]: Получение размерности
От: Аноним  
Дата: 07.05.04 13:39
Оценка:
Здравствуйте, Vi2,
я искренне восхищен! Вариант №3 останется в моем творении.
Посмотрел треды с вашим участием и закусил губу от обиды.
Две недели убил на ваяние (по материалам инета) кода по передаче строк из сишной DLL в VB росредством callback процедуры.
Надо было сразу сюда топать...
Удачи в просветительской деятельности.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.