Исправлено распределение памяти для пользовательских типов в VBA - PullRequest
0 голосов
/ 04 июня 2019

У меня есть определенный пользователем тип в VBA (Excel), и я хочу иметь фиксированный макет памяти для членов, чтобы я мог использовать указатели на более позднем этапе для доступа к этим элементам.

Определяемый пользователем тип выглядит как предоставленный код, и мне нужно передать адреса членов другой программе.

Я ожидал, что VBA структурирует элементы в порядке их инициализации, но почему-то это не так.

Если у вас есть идеи, как решить эту проблему, я был бы очень признателен!

С наилучшими пожеланиями, Lars

Public Type ExampleSet

Example_P_Anteil                 As Single
Example_I_Anteil                 As Single
Example_D_Anteil                 As Single
Example_v0                       As Double
Example_Gang0                    As Integer
Example_Beschleunigung           As Double
Example_Startzeit                As Double

Example_int1                     As Integer
Example_int2                     As Integer
Example_int3                     As Integer

End Type

1 Ответ

3 голосов
/ 04 июня 2019

Я оспариваю ваши выводы.

Public Type TestUDT
    SomeInteger As Integer ' Int16 (I2) at offset 0, padded with 2 bytes
    SomeLong As Long       ' Int32 (I4) at offset 4, no padding
    AnotherLong As Long    ' Int32 (I4) at offset 8, no padding
End Type

Public Sub test()
    Dim udt As TestUDT
    Debug.Print VarPtr(udt)             'expected: X
    Debug.Print VarPtr(udt.SomeInteger) 'expected: X+0
    Debug.Print VarPtr(udt.SomeLong)    'expected: X+4
    Debug.Print VarPtr(udt.AnotherLong) 'expected: X+8
End Sub

Вывод соответствует ожидаемому:

 723094616 
 723094616 
 723094620 
 723094624 

Пользовательские типы (UDT) определены в спецификациях языка как:

Линейная конкатенация значений агрегированных данных, возможно, с заполнением, определенным реализацией между значениями данных.

Заполнение может быть тем, что вас отбрасывает, но UDTвсе еще линейная конкатенация его членов.

Используйте функцию LenB, чтобы определить длину члена (или UDT в целом):

Dim foo As ExampleSet
Debug.Print VarPtr(foo), LenB(foo)

Если UDT содержит строки, определите их как фиксированную длину, если необходимо исправить смещения элементов, следующих за ним:

Public Type TestUDT
    SomeString As String * 10
    '...
End Type

Тем не менее, удачи в доступе к этим указателям вне процесса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...