Передача данных в VB

Тема в разделе "WASM.BEGINNERS", создана пользователем OFFSIDE, 23 сен 2006.

  1. OFFSIDE

    OFFSIDE New Member

    Публикаций:
    0
    Регистрация:
    23 сен 2006
    Сообщения:
    106
    Пробую писать dll для обработки текстовой информации под визуал бейсик. Не могу понять, почему при возврате адреса переменной в еах приложение на ВБ падает? Возможно надо передавать не адрес, а саму переменную? Но как, если еах - это два байта? Можно ли из dll вернуть переменную, а именно текст, как результат обработки функции, а не делать дополнительную переменную, посылаемую в вызове dll - ной функции?

    StrProc proc stroka:dword
    fn MessageBox,0,"Да",stroka,0
    lea eax,stroka
    ret
    StrProc Endp

    Пример тривиальный, хочу обработать переменную и вернуть ее же:

    StrProc proc stroka1:dword,stroka2:dword
    fn MessageBox,0,"Да",stroka1,0
    mov eax,stroka1
    mov stroka2,eax
    ret
    StrProc Endp
     
  2. asmfan

    asmfan New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2006
    Сообщения:
    1.004
    Адрес:
    Abaddon
    а причем здесь Entry Point?
    хороший тон - вызывающий предоставляет буфер (указатель) и его размер, вызываемый с ним работает.
     
  3. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    OFFSIDE
    VB оперирует не ASCIIZ, а BSTR (не уверен) и VARIANT. Читай доку по ним, статьи и пробуй. Ещё посоветовал бы прочитать статьи GPcH на этом сайте, он VB расковырял вдоль и поперёк - наверняка описал, как VB со строками работает.
     
  4. OFFSIDE

    OFFSIDE New Member

    Публикаций:
    0
    Регистрация:
    23 сен 2006
    Сообщения:
    106
    asmfan

    Тон то кончно, хороший, но не всегда известен размер буфера.

    IceStudent

    Спасибо, начал поиск
     
  5. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    попробуй так:
    Код (Text):
    1. mov edx, stroka2
    2. mov [edx], eax
    ну и (в данном примере не важно, но) предохраняй регистры на будущее
     
  6. OFFSIDE

    OFFSIDE New Member

    Публикаций:
    0
    Регистрация:
    23 сен 2006
    Сообщения:
    106
    masquer

    А что мне это дает?
    Про регистры понял, сохраню в стек
    Может
    mov eax,[edx]
    ???
     
  7. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    IceStudent
    И да, и нет ;)
    Родные строки VB это BSTR. Но есть одно исключение для работы с dll и API - если в экспортируемой функии объявить строковый параметр ByVal, то BSTR при вызове преобразуется к ASCIIZ и в функию передается обычный указатель lpsz, а при возврате ASCIIZ опять копируется в BSTR - коряво конечно, но работает ;)
    Код (Text):
    1. Пример  
    2. Public Declare Function GetWindowsDirecory Lib "kernel32.dll" Alias "GetWindowsDirectoryA" _
    3.                                (ByVal S As String, ByVal MaxLen As Long) As Long
    4. sub Foo()
    5.   Dim S As String, i as Long
    6.   S = String$(256,0)
    7.   i = GetWindowsDirectory(S,256)
    8.   'если "вдруг" не хватило размера буфера :D
    9.   'if i > 256 then
    10.   '  S = String$(i,0)
    11.   '  GetWindowsDirectory(S,256)
    12.   'end if
    13. end sub
    masquer
    Лучше не пробовать ;
     
  8. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    почему нет? мы же не видим как объявлена переменная?

    хотя лично я забил трахатся с VB и обычной длл при работе хоть с какими-то строками - с актив_х все намного проще стало
     
  9. Quantum

    Quantum Паладин дзена

    Публикаций:
    0
    Регистрация:
    6 янв 2003
    Сообщения:
    3.143
    Адрес:
    Ukraine
    OFFSIDE
    А где код приложения?

    4 байта

    leo уже обьяснил как это сделать. Как альтернативный вариант, можно ещё так сделать:
    Код (Text):
    1. Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
    2.  
    3. ' Convert ASCIIz -> String
    4. Function ToBSTR() As String
    5.         ToBSTR = String$(256,0)
    6.         CopyMem ByVal ToBSTR, ByVal some_func, 256
    7. End Function
    some_func - это имя функции в DLL, которая возвращает ASCIIz строку.
     
  10. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Имхо, самое правильное - вернуть в VB-прогу то, что она ожидает, т.е. BSTR. BSTR получается очень просто: для этого есть api - SysAllocStringByteLen

    Примерно так:
    Код (Text):
    1. Private Declare Function SomeFunc Lib "mylib" (ByVal iStr1 As String, ByVal iStr2 As String) As String
    2.  
    3. Dim OutputStr As String
    4. OutputStr = SomeFunc(ByVal "hello", ByVal " world")
    5. MsgBox OutputStr
    6.  
    7. ;----------------------------------------
    8. SomeFunc proc uses ebx esi edi lpInput1:DWORD, lpInput2:DWORD
    9.     invoke  lstrlen,lpInput1
    10.     mov     ebx,eax
    11.     invoke  lstrlen,lpInput2
    12.     mov     esi,eax
    13.     lea     ecx,[ebx+eax+1]
    14.     invoke  SysAllocStringByteLen, NULL, ecx
    15.     mov     edi,eax
    16.     invoke  lstrcpy, edi, lpInput1
    17.     mov     byte ptr[edi+ebx],32
    18.     invoke  lstrcat,edi,lpInput2
    19.     mov     eax,edi
    20.     ret
    21. SomeFunc endp
     
  11. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    да, вот только VB априори считает строки из обычных длл-ек как asciiz (в MSDN была даже статья этому посвященная), а самый наименее геморойный путь работы с VB (а заодно и .NET) это ActiveX
     
  12. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    тут, кстати, надо так сделать:
    mov byte ptr[edi+ebx],0

    Ну, и в твоем примере BSTR даже и не пахнет :) для этого надо после SysAllocStringByteLen юзать MultiByteToWideChar, однако в данном случае это будет как мертвому припарки - VB только первый символ возьмет.
     
  13. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Ну почитайте ещё раз внимательно о BSTR, и не надо мешать в кучу multybyte и BSTR.
    В примере есть опечатка (писал на коленке): вместо
    mov byte ptr[edi+ebx],32
    нужно
    mov word ptr[edi+ebx],32

    и всё прекрасно работает. Из dll возвращается слепленная строка "hello world".
    И прекрасно отображается в мессаджбоксе.
    А VB при возврате строки из dll сам, без постороннего участия автоматом конвертирует строки в юникод, поэтому никакие MultiByteToWideChar не нужны.
     
  14. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    Из МСДН:
    Я по предыдущему посту понял, что надо бстр _вернуть_ в VB, поэтому просто указываю, что код этой фразе не соответствует.

    можно и так, если задумывалось два пробела между словами.

    Я об этом же и говорю - обычная длл-ка BSTR вернуть напрямую не может :)

    Автору топика - курить статью из мсдн "How to Pass a String or String Arrays Between VB and a C DLL" там все что нужно - расписано
     
  15. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Какие двойные пробелы??
    mov word ptr[edi+ebx],32 - это что, ДВОЙНОЙ пробел ????

    Почему бы не взять приведенный мной пример и не попробовать, что получится на самом деле, не занимаясь умозрительными заключениями, и при этом не имея понятия о предмете разговора?
    Компилируй приведенный код в dll, и вызывай из VB. Смотри сколько там пробелов. Если есть сомнения, можешь применить Len к результирующей строке.


    SysAllocStringByteLen

    Takes an ANSI string as input, and returns a BSTR that contains an ANSI string. Does not perform any ANSI-to-Unicode translation.
     
  16. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    пробел №1
    пробел №2

    Еще будут тупые вопросы?

    У тебя слишком завышенное мнение о своем понимании предмета разговора и очень заниженное обо всех остальных. Это порочная практика - заканчивается обычно тем, что тебя возят мордой лица по собственному говну. Месье мазохист?

    Тыкни плиз в код, где именно у тебя отквоченное происходит и посмотри в отладчике, что именно возвращает SysAllocStringByteLen с нулевым первым аргументом.
     
  17. Bohdan200

    Bohdan200 New Member

    Публикаций:
    0
    Регистрация:
    13 сен 2005
    Сообщения:
    134
    Адрес:
    Lviv
    [offtop]
    Мои познания в VB стремятся к NULL (о чем я и не жалею :) ), но это просто УЖОС
    [/offtop]
     
  18. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    Соображалки не хватило, чтобы понять что " world" - опечатка ?? При том, что специально вставляется word ptr[], 32 :)))

    Отквоченное приведено для того, чтобы было понятно, что SysAllocStringByteLen никаких преобразований не производит, и никаких wide-char на выходе не даёт. То, что она используется с нулевым параметром - это для того, чтобы получить пустой каркас bstr, который VB адекватно воспринимает, и который уже потом заполняется lstrcpy/lstrcat.

    Что ещё непонятно?
     
  19. masquer

    masquer wasm.ru

    Публикаций:
    0
    Регистрация:
    13 сен 2002
    Сообщения:
    890
    Адрес:
    Николаев
    сильно много "опечаток" на такой маленький код, кроме того я никаких претензий к этому не имею и никаких выводов не делал, просто указал на это - к теме обсуждения это мало относится

    для VB это не BSTR, а воспринимает он только asciiz. Фактически с точки зрения VB ты выделил размер_строк*2 + 4 байт в хипе процесса и заполнил его asciiz строкой, все, ни о каких BSTR тут и речи нет. С тем же успехом можно было и HeapAlloc заюзать.
     
  20. cresta

    cresta Active Member

    Публикаций:
    0
    Регистрация:
    13 июн 2004
    Сообщения:
    2.257
    этот " world", к которому ты прицепился, никакого влияния на работоспособность кода не оказывает. Это данные, а не код. Можно написать что угодно, хоть десять пробелов подряд. Но тебе надо за что-то зацепиться, а то день будет прожит зря...

    Зачем ещё лишние движения? Смещать указатель на 4 байта, вызывать lstrlen, сохранять длину строки. А что потом делать с этой памятью? Как освобождать? Вызывать StrPtr? вычитать 4 из этого адреса и полученное отдавать в HeapFree? К чему этот весь хлам?

    SysAllocStringByteLen и больше ничего. oleaut32 сама заполнит длину строки. И VB сам освободит эту память по выходу из процедуры.