Страница: 1 |
Страница: 1 |
Вопрос: Память, указатели
Добавлено: 27.02.05 11:32
Автор вопроса: Vit | Web-сайт:
Получить адрес переменной можно при помощи функций типа VarPtr.
В моём случае, я использую функцию StrPtr - получаю указатель на строку. Но, как сделать обратное - указатель перевести в переменную. Пример тот же самый, но теперь из указателя на строку нужно получить саму строку. Пробовал API функцией CopyMemory (точнее RtlMoveMemory) с параметрами:
(Dest Src Len)
- Any, Any, Long
- String, Long, Long
Программа вылетает. Как нужно действовать?
Ответы
Всего ответов: 11
Номер ответа: 1
Автор ответа:
sne
Разработчик Offline Client
ICQ: 233286456
Вопросов: 34
Ответов: 5445
Web-сайт:
Профиль | | #1
Добавлено: 27.02.05 16:29
Для начала необходимо выделить память... Да и вызов ее может существенно повлиять на результат
Номер ответа: 2
Автор ответа:
Neco
ICQ: 247906854
Вопросов: 133
Ответов: 882
Web-сайт:
Профиль | | #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-сайт:
Профиль | | #3
Добавлено: 28.02.05 01:42
Гомен, функцию, кажись нельзя объявлять Any...
Номер ответа: 4
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #4
Добавлено: 28.02.05 11:11
ИМХО, это невозможно. Можешь разве что запоминать имя переменной в строке, а затем проверять адрес.
Номер ответа: 5
Автор ответа:
GSerg
Вопросов: 0
Ответов: 1876
Профиль | | #5
Добавлено: 06.03.05 15:03
Не могу представить ситуацию, когда потребовалось бы сохранять StrPtr, чтобы потом снова его вернуть...
Но если уж очень надо, тогда
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-сайт:
Профиль | | #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-сайт:
Профиль | | #8
Добавлено: 06.03.05 22:43
Можно и с ByVal'ом объявлять и гибкость останется той-же, но попросту надо будет использовать VarPtr, StrPtr и пр....
Номер ответа: 9
Автор ответа:
CyRax
Разработчик Offline Client
ICQ: 204447456
Вопросов: 180
Ответов: 4229
Web-сайт:
Профиль | | #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-сайт:
Профиль | | #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-х байт по тем же адресам, только во втором случае - через промежуточную переменную.