Пробую писать 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
а причем здесь Entry Point? хороший тон - вызывающий предоставляет буфер (указатель) и его размер, вызываемый с ним работает.
OFFSIDE VB оперирует не ASCIIZ, а BSTR (не уверен) и VARIANT. Читай доку по ним, статьи и пробуй. Ещё посоветовал бы прочитать статьи GPcH на этом сайте, он VB расковырял вдоль и поперёк - наверняка описал, как VB со строками работает.
попробуй так: Code (Text): mov edx, stroka2 mov [edx], eax ну и (в данном примере не важно, но) предохраняй регистры на будущее
IceStudent И да, и нет Родные строки VB это BSTR. Но есть одно исключение для работы с dll и API - если в экспортируемой функии объявить строковый параметр ByVal, то BSTR при вызове преобразуется к ASCIIZ и в функию передается обычный указатель lpsz, а при возврате ASCIIZ опять копируется в BSTR - коряво конечно, но работает Code (Text): Пример Public Declare Function GetWindowsDirecory Lib "kernel32.dll" Alias "GetWindowsDirectoryA" _ (ByVal S As String, ByVal MaxLen As Long) As Long sub Foo() Dim S As String, i as Long S = String$(256,0) i = GetWindowsDirectory(S,256) 'если "вдруг" не хватило размера буфера :D 'if i > 256 then ' S = String$(i,0) ' GetWindowsDirectory(S,256) 'end if end sub masquer Лучше не пробовать ;
почему нет? мы же не видим как объявлена переменная? хотя лично я забил трахатся с VB и обычной длл при работе хоть с какими-то строками - с актив_х все намного проще стало
OFFSIDE А где код приложения? 4 байта leo уже обьяснил как это сделать. Как альтернативный вариант, можно ещё так сделать: Code (Text): Private Declare Sub CopyMem Lib "kernel32" Alias "RtlMoveMemory" (pDst As Any, pSrc As Any, ByVal ByteLen As Long) ' Convert ASCIIz -> String Function ToBSTR() As String ToBSTR = String$(256,0) CopyMem ByVal ToBSTR, ByVal some_func, 256 End Function some_func - это имя функции в DLL, которая возвращает ASCIIz строку.
Имхо, самое правильное - вернуть в VB-прогу то, что она ожидает, т.е. BSTR. BSTR получается очень просто: для этого есть api - SysAllocStringByteLen Примерно так: Code (Text): Private Declare Function SomeFunc Lib "mylib" (ByVal iStr1 As String, ByVal iStr2 As String) As String Dim OutputStr As String OutputStr = SomeFunc(ByVal "hello", ByVal " world") MsgBox OutputStr ;---------------------------------------- SomeFunc proc uses ebx esi edi lpInput1:DWORD, lpInput2:DWORD invoke lstrlen,lpInput1 mov ebx,eax invoke lstrlen,lpInput2 mov esi,eax lea ecx,[ebx+eax+1] invoke SysAllocStringByteLen, NULL, ecx mov edi,eax invoke lstrcpy, edi, lpInput1 mov byte ptr[edi+ebx],32 invoke lstrcat,edi,lpInput2 mov eax,edi ret SomeFunc endp
да, вот только VB априори считает строки из обычных длл-ек как asciiz (в MSDN была даже статья этому посвященная), а самый наименее геморойный путь работы с VB (а заодно и .NET) это ActiveX
тут, кстати, надо так сделать: mov byte ptr[edi+ebx],0 Ну, и в твоем примере BSTR даже и не пахнет для этого надо после SysAllocStringByteLen юзать MultiByteToWideChar, однако в данном случае это будет как мертвому припарки - VB только первый символ возьмет.
Ну почитайте ещё раз внимательно о BSTR, и не надо мешать в кучу multybyte и BSTR. В примере есть опечатка (писал на коленке): вместо mov byte ptr[edi+ebx],32 нужно mov word ptr[edi+ebx],32 и всё прекрасно работает. Из dll возвращается слепленная строка "hello world". И прекрасно отображается в мессаджбоксе. А VB при возврате строки из dll сам, без постороннего участия автоматом конвертирует строки в юникод, поэтому никакие MultiByteToWideChar не нужны.
Из МСДН: Я по предыдущему посту понял, что надо бстр _вернуть_ в VB, поэтому просто указываю, что код этой фразе не соответствует. можно и так, если задумывалось два пробела между словами. Я об этом же и говорю - обычная длл-ка BSTR вернуть напрямую не может Автору топика - курить статью из мсдн "How to Pass a String or String Arrays Between VB and a C DLL" там все что нужно - расписано
Какие двойные пробелы?? 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.
пробел №1 пробел №2 Еще будут тупые вопросы? У тебя слишком завышенное мнение о своем понимании предмета разговора и очень заниженное обо всех остальных. Это порочная практика - заканчивается обычно тем, что тебя возят мордой лица по собственному говну. Месье мазохист? Тыкни плиз в код, где именно у тебя отквоченное происходит и посмотри в отладчике, что именно возвращает SysAllocStringByteLen с нулевым первым аргументом.
Соображалки не хватило, чтобы понять что " world" - опечатка ?? При том, что специально вставляется word ptr[], 32 )) Отквоченное приведено для того, чтобы было понятно, что SysAllocStringByteLen никаких преобразований не производит, и никаких wide-char на выходе не даёт. То, что она используется с нулевым параметром - это для того, чтобы получить пустой каркас bstr, который VB адекватно воспринимает, и который уже потом заполняется lstrcpy/lstrcat. Что ещё непонятно?
сильно много "опечаток" на такой маленький код, кроме того я никаких претензий к этому не имею и никаких выводов не делал, просто указал на это - к теме обсуждения это мало относится для VB это не BSTR, а воспринимает он только asciiz. Фактически с точки зрения VB ты выделил размер_строк*2 + 4 байт в хипе процесса и заполнил его asciiz строкой, все, ни о каких BSTR тут и речи нет. С тем же успехом можно было и HeapAlloc заюзать.
этот " world", к которому ты прицепился, никакого влияния на работоспособность кода не оказывает. Это данные, а не код. Можно написать что угодно, хоть десять пробелов подряд. Но тебе надо за что-то зацепиться, а то день будет прожит зря... Зачем ещё лишние движения? Смещать указатель на 4 байта, вызывать lstrlen, сохранять длину строки. А что потом делать с этой памятью? Как освобождать? Вызывать StrPtr? вычитать 4 из этого адреса и полученное отдавать в HeapFree? К чему этот весь хлам? SysAllocStringByteLen и больше ничего. oleaut32 сама заполнит длину строки. И VB сам освободит эту память по выходу из процедуры.