Visual Basic, .NET, ASP, VBScript
 

   
   
     

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

Страница: 1 |

 

  Вопрос: Память, указатели Добавлено: 27.02.05 11:32  

Автор вопроса:  Vit | Web-сайт: www.home-soft.jino-net.ru
Получить адрес переменной можно при помощи функций типа VarPtr.
В моём случае, я использую функцию StrPtr - получаю указатель на строку. Но, как сделать обратное - указатель перевести в переменную. Пример тот же самый, но теперь из указателя на строку нужно получить саму строку. Пробовал API функцией CopyMemory (точнее RtlMoveMemory) с параметрами:
  (Dest Src Len)
 - Any, Any, Long
 - String, Long, Long
Программа вылетает. Как нужно действовать?

Ответить

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

Номер ответа: 1
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #1
Добавлено: 27.02.05 16:29
Для начала необходимо выделить память... Да и вызов ее может существенно повлиять на результат ;)

Ответить

Номер ответа: 2
Автор ответа:
 Neco



ICQ: 247906854 

Вопросов: 133
Ответов: 882
 Web-сайт: neco.pisem.net
 Профиль | | #2
Добавлено: 28.02.05 01:38
А я читал, что CopyMemory ваще нельзя использовать для работы со строками неопределённой длины (там на это был сделан упор), хотя помню, что у меня как-то выходило, но там ещё какая-то обезьянка с юникодом вылезла. VB хранит строки в юникоде и копируемые байты надо брать через один.
А может получиться создав функцию типа этой:
Private function getStrFromPtr(lngPtr as Any) as String
getstrfromptr=lngptr
end function
Попробуй в вариациях, объяви функцию может как Any или вариантом, параметр передай ByVal, ну короче поэспериментируй - вполне возможно, что получиться и не придёться писать библию на другом языке. 8)

Ответить

Номер ответа: 3
Автор ответа:
 Neco



ICQ: 247906854 

Вопросов: 133
Ответов: 882
 Web-сайт: neco.pisem.net
 Профиль | | #3
Добавлено: 28.02.05 01:42
Гомен, функцию, кажись нельзя объявлять Any...

Ответить

Номер ответа: 4
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #4
Добавлено: 28.02.05 11:11
ИМХО, это невозможно. Можешь разве что запоминать имя переменной в строке, а затем проверять адрес.

Ответить

Номер ответа: 5
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #5 Добавлено: 06.03.05 15:03
Не могу представить ситуацию, когда потребовалось бы сохранять StrPtr, чтобы потом снова его вернуть...

Но если уж очень надо, тогда
Option Explicit

Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
Private Declare Function GetMem4 Lib "msvbvm60" (ByVal pSrc As Long, ByVal pDst As Long) As Long

Private Sub Form_Load()
  Dim s As String
  
  s = "Гы!"
  MsgBox StringFromStrPtr(StrPtr(s))
End Sub

Private Function StringFromStrPtr(ByVal sPtr As Long) As String
  Dim s As Long
  
  GetMem4 sPtr - 4, VarPtr(s)
  StringFromStrPtr = String$(s, 0)
  CopyMemory ByVal StrPtr(StringFromStrPtr), ByVal sPtr, s
End Function

Ответить

Номер ответа: 6
Автор ответа:
 Sharp


Лидер форума

ICQ: 216865379 

Вопросов: 106
Ответов: 9979
 Web-сайт: sharpc.livejournal.com
 Профиль | | #6
Добавлено: 06.03.05 15:37
Есть какой-нибудь смысл в том, чтобы объявлять CopyMemory с ByRef'ами?

Ответить

Номер ответа: 7
Автор ответа:
 GSerg



Вопросов: 0
Ответов: 1876


 Профиль | | #7 Добавлено: 06.03.05 15:42
Есть. Повышается гибкость вызова (и ответственность вызывающего :))

Например, чтобы указать в качестве источника указатель на переменную, достаточно написать её имя. Если бы CopyMemory был объявлен ByVal, пришлось бы писать ещё и VarPtr.
Если работа идёт исключительно с вычисляемыми адресами, то, в принципе, можно в декларации написать ByVal.
Но написание ByRef не отменяет ByVal, просто нужно будет его указывать при вызове...

В общем, просто выше гибкость :)

Ответить

Номер ответа: 8
Автор ответа:
 sne



Разработчик Offline Client

ICQ: 233286456 

Вопросов: 34
Ответов: 5445
 Web-сайт: hw.t-k.ru
 Профиль | | #8
Добавлено: 06.03.05 22:43
Можно и с ByVal'ом объявлять и гибкость останется той-же, но попросту надо будет использовать VarPtr, StrPtr и пр....

Ответить

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



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #9
Добавлено: 07.03.05 00:57
Хм, а я подумал тебе имя переменной нужно :)
Тогда там всё просто, в [StrPtr-4] хранится длина строки, ну и по ней копируешь нужное количество слов с помощью CopyMemory.

CopyMemory скопированно из API-viewer'а, так что сам он ничего не выдумывал - сработал по шаблону, а вот GetMem4 лучше объявить так.
Declare Sub GetMem4 Lib "msvbvm60" (ByVal Addr As Long, RetVal As Long)

Ответить

Номер ответа: 10
Автор ответа:
 CyRax



Разработчик Offline Client

ICQ: 204447456 

Вопросов: 180
Ответов: 4229
 Web-сайт: basicproduction.nm.ru
 Профиль | | #10
Добавлено: 07.03.05 01:01

 Если бы CopyMemory был объявлен ByVal

 CopyMemory - это она, функция (женского рода если ты не понял).

Ответить

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



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #11 Добавлено: 09.03.05 09:49
Кстати, а отчего такая фишка

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)

Dim a As String
Dim b As String
Dim c As Long


Так вот,

CopyMemory a, b, 4&

работает, а

CopyMemory c, b, 4&
CopyMemory a, c, 4&

не работает? Где я что-то упустил? Вроде бы операция одна, копирование 4-х байт по тем же адресам, только во втором случае - через промежуточную переменную.

Ответить

Страница: 1 |

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



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