Получить структуру из ссылки

Программирование на Visual Basic, главный форум. Обсуждение тем программирования на VB 1—6.
Даже если вы плохо разбираетесь в VB и программировании вообще — тут вам помогут. В разумных пределах, конечно.
Правила форума
Темы, в которых будет сначала написано «что нужно сделать», а затем просьба «помогите», будут закрыты.
Читайте требования к создаваемым темам.
paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Получить структуру из ссылки

Сообщение paz » 17.02.2005 (Чт) 7:38

Здравствуйте коллеги.

У меня следующая проблема. Есть бибилиотека типов, в ней интерфейс а у него следующий метод (сишное описание из MSDN):

Код: Выделить всё
SCODE SomeFunction(
  myStructure ** ppStructureValue
);


описание структуры myStructure у меня есть. При вызове этого метода, а вызываю его я так:

Код: Выделить всё
dim mystruct as myStructure
result = SomeFunction(mystruct)


в mystruct записывается какая то лабуда. Причем в первые четыре байта ;))) . То есть мне в структуру вместо оной записался указатель.

Помогите пожалуйста правильно выполнить вызов процедуры а то я в VB6 ни бум-бум. В C++ это мигом решается а в Бейсике то указателей нет :cry:

Заранее благодарю.

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 7:40

Забыл сказать что аргумент ppStructureValue в функции является выходным

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.02.2005 (Чт) 8:00

Гы :)

Ента функция сама отводит память под структуру и возвращает указатель на неё? Если да, то передаём в функцию byref a as long, получаем результат в этом лонге и делаем copymemory mystruct, byval a, len(mystruct)

Кстати, потом память кто освобождать будет? :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 8:58

GSerg писал(а):Гы :)

Ента функция сама отводит память под структуру и возвращает указатель на неё? Если да, то передаём в функцию byref a as long, получаем результат в этом лонге и делаем copymemory mystruct, byval a, len(mystruct)

Кстати, потом память кто освобождать будет? :)


Спасиба бальшое еще раз.

Уан море куейшен: объясните дурню как byref a as long передать в функцию если она уже описана в tlb?
то есть myfunction(byref a) ?
myfunction(varptr(a)) ?

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Сообщение Vi » 17.02.2005 (Чт) 9:10

...как byref a as long передать в функцию если она уже описана в tlb?

Если функция описана в TLB, то ничего делать уже не нужно, потому как не поможет. VB сам понимает, что нужно сделать.

Однако написанное тобой:

dim mystruct as myStructure
result = SomeFunction(mystruct)

не предполагает вызов интерфейсного метода, а, следовательно, предполагает самопальную TLB.

Так что покажи описание этой функции в TLB (или IDL, который использовался для построения TLB).
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 9:49

Vi писал(а):...как byref a as long передать в функцию если она уже описана в tlb?

Если функция описана в TLB, то ничего делать уже не нужно, потому как не поможет. VB сам понимает, что нужно сделать.
не предполагает вызов интерфейсного метода, а, следовательно, предполагает самопальную TLB.

Так что покажи описание этой функции в TLB (или IDL, который использовался для построения TLB).


TLB самопальный :) но вызов я конечно криво написал - на самом деле там интерфейс.

вобщем давайте по порядку:

в MSDN метод описан так

Код: Выделить всё
SCODE GetValue(
  PROPVARIANT ** ppPropValue
);

Parameters
ppPropValue
[out] Pointer to an output variable that receives a pointer to the PROPVARIANT structure that contains the value-type property.

в IDL вот я описал так

Код: Выделить всё
IFilterReturnCodes _stdcall GetValue([out] PROPVARIANT *ppPropValue);


вызываю вот так

Код: Выделить всё
scode = filter.GetValue(mystruct)


в результате в структуре только первые 4 байта запонены - подозрение на то что указатель туда попал.

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 12:31

Лююди а как в функцию передать ссыллку на Long??? :?:

Amed
Алфизик
Алфизик
 
Сообщения: 5346
Зарегистрирован: 09.03.2003 (Вс) 9:26

Сообщение Amed » 17.02.2005 (Чт) 12:35

Код: Выделить всё
SomeFunction(ByRef Val As Long)?

ByRef опускается, и вызывается просто, как
Код: Выделить всё
SomeFunction(Val As Long)

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.02.2005 (Чт) 12:38

А ты в tlb напиши параметр типа int*.
А для максимальной гибкости напиши void*, и передавай вообще что хочешь :)

Кстати, PROPVARIANT - это случаем не обычная наша Variant? Если да, то напиши ByRef VARIANT :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 12:53

GSerg писал(а):А ты в tlb напиши параметр типа int*.
А для максимальной гибкости напиши void*, и передавай вообще что хочешь :)

Кстати, PROPVARIANT - это случаем не обычная наша Variant? Если да, то напиши ByRef VARIANT :)


PROPVARIANT это структура такого вида

Код: Выделить всё
typedef struct PROPVARIANT { 
VARTYPE vt; 
WORD wReserved1; 
WORD wReserved2; 
WORD wReserved3; 
   union { CHAR cVal;   
               UCHAR bVal;
               SHORT iVal;
                .....
             }
} PROPVARIANT


вроде на variant не похоже.



Я написал в IDL параметр как void *ppValue

С каким параметром функцию то вызывать? со структурой или лонгом? если я туда структуру пихаю то она мне только 4 байта первых пишет, если лонг туда пишу то возвращает какоето значение..Что мне с этим значением делать? CopyMemory mystruct, longValue, sizeof(mystruct) ?

Вы извиняйте конечно за тупые вопросы но я просто не понимаю как в васике все это утсроено. :(

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.02.2005 (Чт) 13:00

Гы гы гы :)
Это именно наша Variant :)

ByRef VARIANT объявляй, передавай обычную переменную Variant, ByRef :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 13:22

GSerg писал(а):Гы гы гы :)
ByRef VARIANT объявляй, передавай обычную переменную Variant, ByRef :)


Люди извиняйте , но я не врубаюсь в это выражение "ByRef VARIANT объявляй, передавай обычную переменную Variant, ByRef"

как это написать - напишите строчку примера на VB как по ссылке передавать и на меня снизойдет проясненье и я от вас отстану :))
ByRef это ведь используется в описании функций или я что то недопонял?

Вобщем как в бородатом анекдоте рукой покажите :)

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.02.2005 (Чт) 13:27

В tlb напиши: VARIANT*

Потом просто объяви dim v as variant и передавай :)
А если рухнет, напиши VARIANT**, я чё-то не уверен в этом моменте :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 13:38

GSerg писал(а):В tlb напиши: VARIANT*

Потом просто объяви dim v as variant и передавай :)
А если рухнет, напиши VARIANT**, я чё-то не уверен в этом моменте :)


написал VARIANT* - рухнула. :(

написал VARIANT** - ругается при компиляции следующи матом : "Compile error: Function or interface marked as restricted, or the function uses an Automation type not supported in Visual Basic"

Чтоже делать? :cry:

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.02.2005 (Чт) 13:51

А вот это сложно :)

Для начала вернёмся к вопросу о том, как размещается память под возвращаемую структуру, и кто и как обязан её освобождать.
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 14:02

GSerg писал(а):А вот это сложно :)

Для начала вернёмся к вопросу о том, как размещается память под возвращаемую структуру, и кто и как обязан её освобождать.


Я не в курсе как там с памятью дела, вроде функция сама создает структуру в памяти и передает указетель на нее.

[out] Pointer to an output variable that receives a pointer to the PROPVARIANT structure that contains the value-type property

Может вариант с VARIANT так не прокатит - может все таки как нибудь через LONG и потом CopyMemory? [/i]

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Сообщение Vi » 17.02.2005 (Чт) 14:03

Ох не нравятся мне эти манипуляции.
paz писал(а):в MSDN метод описан так
SCODE GetValue([out] PROPVARIANT ** ppPropValue);
в IDL вот я описал так
FilterReturnCodes _stdcall GetValue([out] PROPVARIANT *ppPropValue);

Вот видишь... Двойной указатель изначально, а ты используешь одиночный. Не удивительно ,что приходит указатель.

Нужно делать так, как советует GSerg через long*, т.е.
SCODE GetValue([out] long* ppPropValue);
И передавать туда целочисленную переменную, которую потом конвертировать в свою структуру. Кстати, почти эквивалентную Variant.
Код: Выделить всё
Dim p as Long, v
ifilterobj.GetValue p
CopyMemory v, byval p, 16 ' 16 байт


Есть еще вариант: передать VarPtr(v) + 8 как адрес реального расположения некоего адреса, только нужно скорректировать значение vt для переменной v
SCODE GetValue([in] long ppPropValue);
Код: Выделить всё
Dim p as Long, v
ifilterobj.GetValue VarPtr(v) + 8
CopyMemory ByVal VarPtr(v), vbVariant Or &H4000, 4

Но я не уверен, т.к. тестировать не на чем.
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 14:48

Нужно делать так, как советует GSerg через long*, т.е.
SCODE GetValue([out] long* ppPropValue);
И передавать туда целочисленную переменную, которую потом конвертировать в свою структуру. Кстати, почти эквивалентную Variant.
Код: Выделить всё
Dim p as Long, v
ifilterobj.GetValue p
CopyMemory v, byval p, 16 ' 16 байт



попробовал. отработала! :)) УРА УРА ! Сенькс!

Есть еще вариант: передать VarPtr(v) + 8 как адрес реального расположения некоего адреса, только нужно скорректировать значение vt для переменной v
SCODE GetValue([in] long ppPropValue);
Код: Выделить всё
Dim p as Long, v
ifilterobj.GetValue VarPtr(v) + 8
CopyMemory ByVal VarPtr(v), vbVariant Or &H4000, 4

Но я не уверен, т.к. тестировать не на чем.


Попробовал и так. Видимо структурка все таки не похожа на Variant бацик говорит что usupported variant type. правда вначале выдал какоето число 1251 но потом не понимает что у него в этой переменной.

Охх придется по значению vt выковыривать вручную... Не в курсях как бы это полегче и с меньшими затратами :))) а то я пока вижу длиннющий select case и Копимемори

Все равно всем огромное спасибо. :lol: :lol: :lol:

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 15:13

В бацике нет Unionа а жаль!!!

нужна обертка для Variant подобной структуры чтобы можно было тащить значения.

Может кто подскажет сурс чтобы велосипедов не городить? Заранее сенькс!

GSerg
Шаман
Шаман
 
Сообщения: 14286
Зарегистрирован: 14.12.2002 (Сб) 5:25
Откуда: Магадан

Сообщение GSerg » 17.02.2005 (Чт) 15:33

Как ты правильно сказал, этого там нет :)
Но когда нас это останавливало? :)

Для того (гы-гы-гы), чтобы сделать union в VB, нужно прочитать мою статейку про SAFEARRAY, после чего описать члены union как отдельные структуры (если эти члены есть тривиальные базовые типы, то и описывать не надо), а потом повызывать CreateSAFEARRAY столько раз, сколько членов у юниона :) И вот он, юнион - правда, в разных переменных, но каждая из них на самом деле ссылается на один и тот же участок памяти :)
Как только вы переберёте все варианты решения и не найдёте нужного, тут же обнаружится решение, простое и очевидное для всех, кроме вас

paz
Новичок
Новичок
 
Сообщения: 27
Зарегистрирован: 04.02.2005 (Пт) 7:44

Сообщение paz » 17.02.2005 (Чт) 15:44

GSerg писал(а):Как ты правильно сказал, этого там нет :)
Но когда нас это останавливало? :)

Для того (гы-гы-гы), чтобы сделать union в VB, нужно прочитать мою статейку про SAFEARRAY, после чего описать члены union как отдельные структуры (если эти члены есть тривиальные базовые типы, то и описывать не надо), а потом повызывать CreateSAFEARRAY столько раз, сколько членов у юниона :) И вот он, юнион - правда, в разных переменных, но каждая из них на самом деле ссылается на один и тот же участок памяти :)


Круто! Шамана однако. :)

Изображение

Ну пошел я читать про сейфмассивы. Надеюсь выйдет каменный цветок откуда надо! :)

Vi
Постоялец
Постоялец
 
Сообщения: 739
Зарегистрирован: 25.01.2002 (Пт) 11:03
Откуда: Россия, Ижевск

Сообщение Vi » 17.02.2005 (Чт) 16:33

paz писал(а):Попробовал и так. Видимо структурка все таки не похожа на Variant бацик говорит что usupported variant type. правда вначале выдал какоето число 1251 но потом не понимает что у него в этой переменной.

Правильно говорит. Однако он должен корректно отображать этот полученный Variant в окне Переменных.

VB не умеет работать с Variant-ами, которые ссылаются на другие типы/структуры. Для этого нужно использовать VariantChangeType или VariantCopyInd (эти функции, кстати, лучше использовать вместо CopyMemory, поскольку они еще и очищают то место, куда копируют).

vbVariant Or &H4000 - это VT_BYREF | VT_VARIANT, а pvarVal заполнилось в результате вызова GetValue VarPtr(v) + 8. Но насколько корректно это получилось - не могу сказать.

PS
Код: Выделить всё
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
            (Destination As Any, Source As Any, ByVal Length As Long)

Private Sub Form_Load()
  Dim v, vv
  CopyMemory ByVal VarPtr(v) + 8, VarPtr(vv), 4
  CopyMemory ByVal VarPtr(v), vbVariant Or &H4000, 4
  ' v - это ссылка на vv - проверяем
  vv = 3
  Debug.Print vv, v
End Sub
Vita
Выше головы не прыгнешь, ниже земли не упадешь, дальше границы не убежишь! (с) КВН


Вернуться в Visual Basic 1–6

Кто сейчас на конференции

Сейчас этот форум просматривают: Yandex-бот и гости: 176

    TopList