На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела Visual Basic: Общие вопросы
Здесь обсуждаются вопросы по языку Visual Basic 1-6 (а так же по схожим языкам, как, например, PowerBASIC).
Вопросы по Visual Basic .NET (это который входит в состав Visual Studio 2002/2003/2005/2008+, для тех, кто не в курсе) обсуждаются в разделе .NET.

Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что Вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются. Студенты, вам сюда: ПОМОЩЬ СТУДЕНТАМ!
4. Используйте теги [ code=vba ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Формулируйте свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной (и более) давности, без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта user posted image FAQ Раздела user posted image Кладовка user posted image Наши Исходники user posted image API-Guide user posted image Поиск по Разделу user posted image MSDN Library Online user posted image Google

Ваше мнение о модераторах: user posted image SCINER, user posted image B.V.
Модераторы: SCINER, B.V.
  
> Не могу вызывать ф-и API из Callback ф-и , Есть Callback функция через AddressOf...
    Я пользуюсь некой DLL через Declare. Эта DLL требует инициализации с передачей ей (через AddressOf) указателя на мою Callback-функцию (на VB), которую эта DLL будет дергать в неопределенные моменты. Пока все ясно. Проблема в том, что я не могу размещать внутри моей Callback-функции никакие вызовы API-функций - происходит крах. Дополнительно сообщю, что DLL написана не мной на С++, публичные вызовы по StdDecl. Как говорят в KB198607 ( http://support.microsoft.com/kb/q198607/ ), виновата несовместимая реализация потоков. Но решения там нет.

    Вот в сильно упрощенном виде код:

    ExpandedWrap disabled
      ' Здесь я объявляю функцию инициализации DLL
       
      Public Declare Function init_DLL Lib "XXX.dll" (ByVal CallbackFunc As Long) As Long
       
      ' Это типа точка входа
       
      Public Sub Main()
         ' Инициирую DLL с передачей ей указателя на мою Callback-функцию
           init_DLL(AddressOf CallbackFunc)
      End Sub
       
      ' А вот и сама Callback-функция в соответствием с требованием DLL
       
      Public Function CallbackFunc(ByVal param1 As Long, ByVal param2 As Long) As Long
          ' невозможно делать вызовы API-функций
      End Function


    Неуклюжее рабочее решение - поставить таймер, который откладывает выполнение асинхронной функции (вместо нее будет вымолняться другая, синхронная ф.) Но мало того, что это не красиво, моя callback функция не сможет возвращать осмысленного значение, т.к. выход из нее раньше, чем собственно выполнение. Как жить-то дальше?
      похоже это действительно ваш случай.

      а стандартные вба функции все работают в таком коллбаке?
      если ваш - то не должны бы все. скорее "почти никакие"
      ...

      если не ваш случай, то

      может быть этой "XXX.dll" сделать LoadLibrary до вызова init_DLL (?)

      ...
      попробуйте нужную апи функцию вызвать предварительно до инициализации внешней библиотеки.
      (или использовать tlb-описатель для задействованных таким образом библиотек)

      ...
      если случай все же ваш, и
      ваш VB-код действительно исполняется потоком, который вб не сам для себя создал
      (а очень похоже по сказанному),
      то, как минимум, нужно инициализировать оле для этого ( в этом) потоке и создать вручную однопоточные ком-апартаменты. (с вытекающей потом терминацией поднятого при завершении потока)

      показать как "надо" - не смогу. так не делал никогда. "книжные знания".
        Jupiter
        Попробуй другой способ работы с потоками.....
          Цитата

          а стандартные вба функции все работают в таком коллбаке?
          если ваш - то не должны бы все. скорее "почти никакие"

          Я могу работать с глобальными и модульными переменными. Вызовы функций VB происходят странно - в основном падает. Даже на On Error GoTo. При этом есть разница, запускаю ли я скомпилированный ехе, или из ide.

          Все описанные здесь рекомендации вызывают у меня ужас. В настоящее время я пишу на С свойю dll-переходник к этой чужой dll в надежде, что оттуда Callback будет работать нормально. Ну а уж свою-то dll со своей же vb-программой я подружить всегда смогу :-) Хотя обидно: я столько преодалел, чтобы заставить эту dll работать непосредственно из-под vb, будь он проклят.
            советы вызывают ужас?

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

            может, все-таки - попробовать loadlibrary сначала?

            --
            а что вас заставляет вообще мучаться с vb?
              2сразу все: А немогли бы Вы описать, каким образом приведенное вами решение позволит "подружить" VB с многопоточностью?
                Цитата Velin @
                2сразу все: А немогли бы Вы описать, каким образом приведенное вами решение позволит "подружить" VB с многопоточностью?

                Там решение такое. Сообщения, посылаемые через Callback (а это именно механизм сообщений) помещаются в буфер внутри моей переходной dll. А VB-программа переодически (увы, по таймеру) синхронно опрашивает эту dll. Многопоточность, если она есть, существует между моей и чужой dll-ми, там все на мьютексах, как и положено. А VB ничего об этом не знает. Такой механизм уже много лет работает для другого источника сообщений. Самому мне вся эта кухня с таймерами не очень нравится. Но пока не перейдем на .net, похоже так и будем в муках изобретать (рожать) велосипеды.
                Сообщение отредактировано: Jupiter -
                  2 Vellin
                  если вы о loadlibrary, то:

                  пока нет ясных оснований считать, что дело именно в многопоточности.
                  пока ясно, что загрузка (и инициализация) dll происходит в момент первого обращения
                  к объявленной через декларе функции. И "предложение" заключается просто в разведении загрузки и инициализации длл от первого обращения к ней за исполнением функции.
                  Это единственное, что я могу определенно вынести непосредственно из первоначально сказанного.

                  Из продолжения может возникать подозрение, что идет какое-то косвенное субклассирование чужого окна. Но чего-то внятного сказать нельзя.
                  Предположение о том, что эта длл передает "чужому" уже существующему на момент передачи потоку адрес функции, которая потом должна быть быполнена в том другом потоке - тоже вполне возможно. и слова некоторые на эту мысль наводят. Если да - то далее идут слова про исполнение вб кода в "чужих" потоках, которые не были созданы системой поддержки исполнения вб-кода.
                  Однако, если нет информации и инструменария понять, что в точности происходит, то идти надо от простых предположений.

                  (так я думаю)
                  :)
                    а вы не пробовали вызывать API функции динамически, т.е. без ее предварительной декларации ?
                      как связано с дружением с многопоточностью:

                      Цитата
                      попробуйте нужную апи функцию вызвать предварительно до инициализации внешней библиотеки.

                      само по себе это мимо кассы. поторопился.

                      Цитата
                      (или использовать tlb-описатель для задействованных таким образом библиотек)

                      это позволит иметь "нормально" построенный вызов апи функции. адрес которой гарантированно известен (на этапе компиляции) в момент вызова. а нужная длл будет
                      гарантирована загружена в адресное простанство программы в момент старта (загрузки).
                      Код вызова апи функции полностью сформирован и не требует поддержки времени выполнения.
                      все имеет хорошие шансы срастись. чужой поток будет иметь дело с кодом не требующим поддержки в момент вызова от среды вб. есть шансы, что все срастется.
                      ...

                      Цитата

                      если случай все же ваш, и
                      ваш VB-код действительно исполняется потоком, который вб не сам для себя создал
                      (а очень похоже по сказанному),
                      то, как минимум, нужно инициализировать оле для этого ( в этом) потоке


                      вб почти 100-процентно полагается на ком. почти все (по крайней мере - все видимые в просмотрщике объектов) функции вб не будут работать, если в исполняющем потоке не инициализирован ком.
                      единственный шанс получить минимально способный к выполнению относительно сложного вб-кода не вб поток - инициализировать в этом потоке ком (типа - олеинитиалайз)


                      Цитата
                      и создать вручную однопоточные ком-апартаменты. (с вытекающей потом терминацией поднятого при завершении потока)

                      так делает сам вб для каждого "своего" потока. говорят, "в принципе" это можно обойти. но лучше следовать его примеру.


                      Цитата
                      показать как "надо" - не смогу. так не делал никогда. "книжные знания".


                      тут вроде пояснять нечего. я - не делал.
                        2 SCINER

                        про динамический вызов.

                        очень может даже быть что прокатит. нужно только придумать какой-то надежный механизм сохранения параметров вызова для вызывающей процедуры. где-нибудь в атомах и/или оконных лонгах.

                        думаю, что это "потребует кодирования". и как по мне - лучше уж описатель прикрутить.
                          еще про динамический вызов.
                          думаю, что так или иначе, код динамического вызова
                          (задействованных в вызове апи-функций) надо строить на tlb.
                            Цитата
                            пока нет ясных оснований считать, что дело именно в многопоточности

                            По Вашему http://support.microsoft.com/kb/q198607/ это не основание?
                              не основание для чего? я не понял, на какое именно место в статье вы хотите точно указать.

                              если на это:
                              Цитата
                              This error may occur immediately following a declared API function call within a Visual Basic callback function


                              то я вроде по русски говорю -
                              попробуйте использовать tlb-описатели.

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


                              кстати, когда я говорил про предварительный вызов до регистрации функции косвенного выполнения, то думал в первую очередь о том, что в данном конкретном случае совсем не обязательно речь идет о "чужом потоке", а,
                              вполне возможно, об особенностях инициализации конкретной xxx
                              И без всяких потоков бывает, что принудительная предварительная загрузка целевой dll стабилизирует работу декларированных функций.

                              если вы еще раз прочитаете статью, на которую сослались, то увидите, что ни в каком предложении она не входит в противоречие с моими утверждениями.
                              (даже если какие-то из них и окажутся неточными - статья своим текстом их непосредственно не опровергает)
                              :)
                                >попробуйте использовать tlb-описатели.

                                Я бы с удовольствием попробовал. Вы только намекните, как именно...
                                В смысле, о чем идет речь в терминах синтаксиса VB?
                                Сообщение отредактировано: Jupiter -
                                  я не понял последнего предложения.

                                  давайте так:
                                  выложите полные точные декларации для ваших функций в проблемной длл
                                  и использованных в функции косвенного вызова апи.
                                  если их не слишком много окажется (типа - 3-4) выложу вам сегодня описатель.
                                  просто закомментируете в проекте свои декларации и подключите описатель
                                    tlb описатель - это библиотека типов. Подключается в прект в References
                                    возьми здесь достаточно полные описатели апи-функций как анси WinTlb3.zip

                                    так и юникод WinTlbU.zip версий апи-функций.

                                    mckinney
                                      Попробовал выводить значение GetCurrentThreadID в sub Main и в Callback функции. Они ОТЛИЧАЮТСЯ.

                                      Вот код моей программы на VB
                                      ExpandedWrap disabled
                                        ' Здесь я объявляю функцию инициализации DLL
                                        Public Declare Function init_DLL Lib "XXX.dll" (ByVal CallbackFunc As Long) As Long
                                         
                                        ' А вот "крутая" функция API.
                                        Private Declare Function Beep Lib "kernel32" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long
                                         
                                        ' Это типа точка входа
                                        Public Sub Main()
                                           ' Инициирую DLL с передачей ей указателя на мою Callback-функцию
                                             init_DLL(AddressOf CallbackFunc)
                                        End Sub
                                         
                                        ' А вот и сама Callback-функция в соответствием с требованием DLL
                                        Public Function CallbackFunc(ByVal param1 As Long, ByVal param2 As Long) As Long
                                            Beep 1000, 500 ' Бу-бух... Упали...
                                        End Function

                                      Вот описания на C из чужой документации. Инициализация (init_DLL) происходит нормально.
                                      ExpandedWrap disabled
                                        DWORD init_DLL (VLSDK_CALLBACK* callback);
                                         
                                        // Прототип функции обратного вызова
                                        typedef int (__stdcall VLSDK_CALLBACK)(DWORD param1, DWORD param2);
                                        Цитата Jupiter @
                                        Вызовы функций VB происходят странно - в основном падает. Даже на On Error GoTo.

                                        ловить надо с помощью SetUnhandledExceptionFilter

                                        см. пример ее использования.
                                        Сообщение отредактировано: Алиса -

                                        Прикреплённый файлПрикреплённый файлCode_Exception.rar (3.87 Кбайт, скачиваний: 70)
                                          Цитата , @
                                          tlb описатель - это библиотека типов. Подключается в прект в References
                                          возьми здесь достаточно полные описатели апи-функций как анси WinTlb3.zip

                                          так и юникод WinTlbU.zip версий апи-функций.

                                          mckinney

                                          Спасибо, я скачал. Я понял, в каком направлении все должно крутиться.
                                          Чтобы получить требуемый win.tlb я должен запустить некий батник. Не люблю я эти батники: они вечно что-нибудь требуют. Вот и в этот раз:
                                          >midl : command line error MIDL1005 : cannot find C preprocessor cl.exe
                                          Может быть у Вас есть win.tlb?
                                            файл больше 200 кб размером -- прилепить не могу.
                                            где-то он лежал в скомпилированном виде - или на вбакселераторе или на сайте у Петерсона.

                                            по всему - из чужого потока вызов происходит.
                                            бип может и сработает. или другой одиночный вызов апи.
                                            с более содержательными алгоритмами будут проблемы.
                                              вот маленький описатель
                                              там только бип
                                              и попытка описать вашу функцию инициализации.

                                              подключите библиотеку
                                              попробуйте сначала закомментировать в своем коде только декларацию бип
                                              проверьте, что работает библиотечной описатель в обычной процедурею
                                              дальше попробуйте запустить в "рабочем" режиме.

                                              попробуйте также закомментировать в свем коде объявление init_DLl.
                                              если объявление в библиотеке составлено неверно, то скомпилированный проект не запустится и дело до точки вызова init_dll не дойдет
                                              Прикреплённый файлПрикреплённый файлBeep.tlb (1.52 Кбайт, скачиваний: 216)
                                                вот маленький описатель
                                                там только бип
                                                и попытка описать вашу функцию инициализации.

                                                подключите библиотеку
                                                попробуйте сначала закомментировать в своем коде только декларацию бип
                                                проверьте, что работает библиотечной описатель в обычной процедурею
                                                дальше попробуйте запустить в "рабочем" режиме.

                                                попробуйте также закомментировать в свем коде объявление init_DLl.
                                                если объявление в библиотеке составлено неверно, то скомпилированный проект не запустится и дело до точки вызова init_dll не дойдет
                                                Прикреплённый файлПрикреплённый файлBeep.tlb (1.52 Кбайт, скачиваний: 240)
                                                  Цитата Victosha @
                                                  вот маленький описатель
                                                  там только бип
                                                  и попытка описать вашу функцию инициализации.
                                                  ...

                                                  Спасио. Эксперимент состоялся. Но утишительного мало.
                                                  Действительно, Beep удалось запустить по Вашей схеме. Но из Callback он все равно падает :-(
                                                  Инициировать длл с помощью даного описателя, к сожалению, невозможно, т.к. для упрощения разговора я опустил еще один аргумент (long), да и имя функции дал более понятное для обсуждения. То есть, если бы я знал, что Вы следаете описание на idl, то конечно бы дал полное описание ф-и инициализации. Все равно, спасибо за поддержку! Буду писать переходник.
                                                  0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                  0 пользователей:


                                                  Рейтинг@Mail.ru
                                                  [ Script execution time: 0,0557 ]   [ 16 queries used ]   [ Generated: 8.11.25, 20:43 GMT ]