HIBYTE, LOBYTE, HIWORD, LOWORD, WORD, DWORD, SHIFT

Здесь можно найти готовые «кирпичики» — части кода, пригодные для построения более крупных проектов, а также решения различных типовых и не очень задач на VB.

Модератор: Brickgroup

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 30.05.2008 (Пт) 15:32

Вот как я понял: функции, объявленные через tlb, загружаются ещё до выполнения какого-либо моего кода, а значит ловить ошибку бесполезно. Это-таки подводный камень.

То есть, когда я хочу чего-нибудь от библиотеки, которая неизвестно, есть ли у пользовотеля, нужно её Declare, чтобы в случае чего поймать ошибку.

А если и я продикларировал, и в тлб есть - откуда будет браться функция?
Артур
 
   

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 30.05.2008 (Пт) 16:05

arthur2 писал(а):Antonariy
нужно использовать VB Watch2.
А что это? Поиском не ищется :cry:
Это абсолютный must have для оптимизации алгоритмов.
Пробел забыл перед двойкой.
Лучший способ понять что-то самому — объяснить это другому.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 30.05.2008 (Пт) 16:36

Antonariy
Спасибо! уже качаю :lol:
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 30.05.2008 (Пт) 16:42

Вот как я понял: функции, объявленные через tlb, загружаются ещё до выполнения какого-либо моего кода, а значит ловить ошибку бесполезно. Это-таки подводный камень.

Функции, объявленные как статически функции в TLB, содержат в себе три характеристики:
1) DLLFileName
2) FunctionAlias
3) FunctionOrdinal

При этом из двух последних используется только одна.

* * *

Концепция модульности предполагает, что PE-файлы подгружаются в АП процесса по мере надобности. Потребность одного PE-модуля в другом обуславливается тем, что один PE-модуль может вызывать функции, располагающиеся в другом.

Поэтому в PE-файлах хранится информация: какие функции предоставляет PE-файл, и какие-функции берёт из других PE-модулей.

Когда в АП процесса загружается модуль, загружаются и все модули, которые требуются для первого. Если хоть один из модулей, в которых нуждается загружаемый, не загружается, обламывается загрузка загружаемого.

Т.к. запуск экзешника - это создание процесса и загрузка в его АП главного модуля (того, который .exe) - то здесь действует тот же принцип. И те же правила облома: если хоть один из модулей, нужных загружаемому, не удаётся загрузить - загрузка обламывается.

В принципе это правильно и логично -- какой смысл что-то продолжать, если куска приложения нет?

* * *

Поскольку С++ создавался как потомок С, а С создавался за долго до появления этих механизмов, в С++ нет возможности языковыми средствами импортировать функцию. Из-за особенностей модели компиляции С/С++ такая возможность даже вряд ли могла бы быть.

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

В VB языковых средств для нормального обычного импорта тоже нет. Но для совместимости с общей концепцией COM, разработчики VB сделали поддержку такого импорта для статических функций из TLB.
Поэтому возможность такого импорта в VB всё-таки есть, но только через TLB, а жаль.

Надо сказать, что TLB намного круче .lib-ок. Хотя бы потому, что их можно собрать самому используя IDL, и они, в отличие от lib-ок, содержат море полезной инфы. В частности, Object Browser (F2) - ничто иное как обозреватель TLB-шек.

VB не поддерживает .lib-ки, а С++ не поддерживает TLB-шки.

В дельфях возможность нормального импорта есть.

* * *

То есть, когда я хочу чего-нибудь от библиотеки, которая неизвестно, есть ли у пользовотеля, нужно её Declare, чтобы в случае чего поймать ошибку.


Для таких DLL нужно использовать использовать LoadLibrary + GetProcAddress + Функтор.

Функторов в явном виде в VB нет, но все Declare-функции являются именно read-only фунторами.

А если и я продикларировал, и в тлб есть - откуда будет браться функция?

Не важно, продекларирвао ты, объявил в тлб или что-то ещё: в VB действует общий принцип для выбора того, какая сущность будет использована, если существует несколько сущностей с одинаковым именем в разных модулях.

Так что представь, что функции объявлены не через Declare и TLB, а просто объявлены в модулях.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 30.05.2008 (Пт) 17:08

А если и я продикларировал, и в тлб есть - откуда будет браться функция?

Не важно, продекларирвао ты, объявил в тлб или что-то ещё: в VB действует общий принцип для выбора того, какая сущность будет использована.

Это я почему спросил: если я ни разу не использовал функцию из тлб, она ведь в ехе не попадёт? А вдруг в тлб есть функция, которую я хотел бы использовать, но опасаюсь, что у пользователя может не оказаться библы. Смогу ли я объявить её как-то через Declare, чтобы в экзешник она попала в этом варианте, а не из тлб? Alias поможет?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 30.05.2008 (Пт) 17:14

Это я почему спросил: если я ни разу не использовал функцию из тлб, она ведь в ехе не попадёт?

Что значит "попадать в exe"?
Функция не попадает в таблицу импорта, если ни разу нигде не используется. Библиотека так же не попадает в таблицу импорта, если ни одна из её экспортируемых функций не импортируется.

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

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

Смогу ли я объявить её как-то через Declare,

Объявить то ты её сможешь почему нет?
чтобы в экзешник она попала в этом варианте, а не из тлб?

Растолку мне понятия "попала в экзешник". Тогда смогу ответить.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 30.05.2008 (Пт) 17:46

Что значит "может не оказаться библы"?
К примеру, хочу прозрачных окон, но не хочу, чтобы в вин98 прога дохла.
Растолку мне понятия "попала в экзешник". Тогда смогу ответить.

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


Окей, пробую плясать от этого абзаца. Если функция объявлена declare, она в таблицу импорта не попадает? Вроде, да.

Если функция есть в тлб, но ни разу не используется, она в таблицу импорта не попадает? Вроде, да.

Допустим, хочу использовать функцию, которая уже есть в тлб, но не хочу, чтобы она попала в таблицу импорта. Поможет ли её деклорация с каким-нибудь отличным от оригинала Alias?
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 30.05.2008 (Пт) 17:50

Окей, пробую плясать от этого абзаца. Если функция объявлена declare, она в таблицу импорта не попадает? Вроде, да.

Не попадает.
Если функция есть в тлб, но ни разу не используется, она в таблицу импорта не попадает? Вроде, да.

Аналогично.

Допустим, хочу использовать функцию, которая уже есть в тлб, но не хочу, чтобы она попала в таблицу импорта. Поможет ли её деклорация с каким-нибудь отличным от оригинала Alias?

Не понял чего именно ты хочешь. Работать с функций нормально, но так, чтобы её не было в таблице импорта, или же тебе просто надо обойти проблемную ситуацию, поюзать Declare-функцию, но так, чтобы VB не принял её за одноимённую функцию в TLB?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 30.05.2008 (Пт) 18:26

Не понял чего именно ты хочешь. Работать с функций нормально, но так, чтобы её не было в таблице импорта, или же тебе просто надо обойти проблемную ситуацию, поюзать Declare-функцию, но так, чтобы VB не принял её за одноимённую функцию в TLB?
Оба два.

Допустим, я сам не знаю, чего хочу. Просто гипотетическая ситуация. Не "зачем это надо", а "как это будет, если я так сделаю":

1 К проекту подключена тлб.
2 В ней есть функция А
3 Я декларирую функцию А, но с псевдонимом В.
4 Я использую функцию по псевдониму В

Попадёт ли такая функция в таблицу импорта?

(а для чего мне это - я чёй-то уже запарился переформулировать :lol: )
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 30.05.2008 (Пт) 18:29

Не попадёт.
Даже если не давать псевдонима B, а четко указывать, что ты хочешь использовать именно Declare-вариант а не TLB-вариант функции.

А указывается это полным именем функции.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

arthur2
Продвинутый гуру
Продвинутый гуру
Аватара пользователя
 
Сообщения: 1688
Зарегистрирован: 23.01.2008 (Ср) 14:35

Сообщение arthur2 » 30.05.2008 (Пт) 19:59

Бинго! :lol:

А указывается это полным именем функции
То есть, вместе с именем модуля, на сколько я понял?

Спасибо! Из тебя получился бы отличный учитель. Мастерски "не понимаешь", пока вопрощающему не удастся внятно сформулировать, чего ему надо. А правильный вопрос - половина ответа. Я по пути и сам понял, чего хочу 8) И представил всё куда менее путанно, чем раньше.

Кстати, не прочитал рассказик по ссылке из соседнего топика? Там один в один про тебя!
Артур
 
   

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 30.05.2008 (Пт) 20:01

То есть, вместе с именем модуля, на сколько я понял?

И с именем библы/проекта. Ибо могут быть два модуля с одинаковым именем.

Не прочёл. Нет времени.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 31.05.2008 (Сб) 12:28

в С++ нет возможности языковыми средствами импортировать функцию

В C++ на уровне языка импортится LoadLibrary с GetProcAddress, после чего производитс легальный там вызов по указателю.
а С++ не поддерживает TLB-шки.

TLB-шки прекрасно цепляются и импортируются из Visual C++. Не стоит утверждать так категорично.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 31.05.2008 (Сб) 17:55

В C++ на уровне языка импортится LoadLibrary с GetProcAddress, после чего производитс легальный там вызов по указателю.

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

TLB-шки прекрасно цепляются и импортируются из Visual C++. Не стоит утверждать так категорично.

Где?
Где-нибудь в Microsoft Visual C++ 2008 возможно, конечно, что да. Но я говорю о MSVCPP6.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 02.06.2008 (Пн) 21:19

Хакер
Гм. И в 6-ом цеплялось на ура.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 02.06.2008 (Пн) 21:28

Где?
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 03.06.2008 (Вт) 18:14

Директива #import точно поддерживается начиная с Visual C++ 5.0. Насчёт более ранних версий не знаю, наврятли их сейчас удастся достать, да и не факт, что тогда вообще были TLB, в эпоху Windows 3.1 то.
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 01.07.2008 (Вт) 11:14

keks-n писал(а):TLB-шки прекрасно цепляются и импортируются из Visual C++. Не стоит утверждать так категорично.
Как это делается? Нужно в VC++ 2005 объявить объект, интерфейс которого описан в tlb.
Лучший способ понять что-то самому — объяснить это другому.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 01.07.2008 (Вт) 21:21

#import directive. Создавать через CoCreateInstance.
TLB подгони - сделаю пример.
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 02.07.2008 (Ср) 8:41

Лучше пример с CoGetObject.
Вложения
DocViewProt.rar
(492 байт) Скачиваний: 212
Лучший способ понять что-то самому — объяснить это другому.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 02.07.2008 (Ср) 22:12

Студии под рукой сейчас нет - глянь по ссылкe, там неплохо расписано:
http://www.cyberguru.ru/programming/vis ... ctive.html
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 03.07.2008 (Чт) 10:42

Неплохо для того, кто хоть что-то понимает. Мне из этой статьи непонятно нихрена.
После подключения соответствующей библиотеки типов с помощью директивы #import будут созданы два файла, которые генерируются в выходном каталоге проекта. Это файл sampl.tlh, содержащий описание классов, и файл sampl.tli, который содержит реализацию членнов классов. Эти файлы будут включены в проект автоматически.
Соответствующей - какой? Той, которая меня интересует (DocViewProt)? Где это писать? Пример там приведен на основе похоже шестой студии, 2005я не генерит *.tli и *.tlh.

Можно пойти другим путем, если он проще - описать интерфейс в самой библиотеке, чтобы можно было подключить ее к VB.

А пока что методом тыка сделал:
Код: Выделить всё
#import "DocView.tlb" no_namespace //в cpp-модуле, где нужно этот объект объявить

IDocView *dv;
HRESULT r = CoGetObject(L"DocView.Application",NULL,IDocView,(void**)&dv);
Объявление студия схавала, но на второй строчке выдала ошибку:
error C2275: 'IDocView' : illegal use of this type as an expression
Лучший способ понять что-то самому — объяснить это другому.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 03.07.2008 (Чт) 20:52

Antonariy
2005-генерит - глянь в сторону папки со сгенерированным исполняемым файлом - там они дефолтно и валяются.
Там же пример с врапперами был? Доберусь до студии, попробую соорудить пример.
Add: глянь ещё здесь, на примере с ADO: http://support.microsoft.com/kb/169496
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 07.07.2008 (Пн) 9:23

Действительно, генерит. Однако понятней от этого не становится, как и пример с враппером. Понимаешь, мои знания c++ находятся на уровне синтаксиса, я даже не понимаю назначения всех файлов в проекте, а ты меня грузишь mfc-шными полноформатными примерами. Все равно, что первокласснику давать решать дифуры. С примерами.
Вот в первой ссылке было написано, что нужно в проект добавить idl. Добавил DocView.idl, сделал что-то еще, уже не помню что, попробовал откомпилировать - ide сообщило, что не найден DocView.h. Что в него писать, не имею ни малейшего представления. Убрал idl, какое-то время экспериментировал на одной интуиции и понятным крохам из MSDN, потом добавил idl опять, на этот раз *.h не запросило, а сделало вид, что моего idl в проекте вообще нет. Что это было 0_о? В результате застрял на ситуации, описанной в предыдущем посте. Чувствую, что не смотря на примеры, нахожусь на верном пути, а косяк в третьем параметре CoGetObject - туда нужно передать "Reference to the ID of an interface that is implemented on the object to be created". Насколько я понял из примеров, это должно быть IID_IDocView, как его описать? Кстати, в интернете примеров на CoGetObject удивительно мало — по две русскоязычных страницы на яндексе и гугле (на английском больше, но в основном муть), — и совсем нет (вернее я не знаю как искать) на использование IID.
Лучший способ понять что-то самому — объяснить это другому.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 07.07.2008 (Пн) 20:30

Если есть IDL - добавляешь в проект, тебе MIDL сгенерит заголовок. В настройках мидла надо ещё прописать, чтобы во второй заголовок эти IID генерились, его надо включить где-то в одном месте, причём после первого, который нужен везде, где данные используются
Изображение

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 08.07.2008 (Вт) 9:05

Это наше обсуждение похоже на ситуацию: слепой тебя просит провести его из пункта А в пункт Б, а ты суешь ему карту :)

1) Заголовок не генерится, генерится tlb.
2) Как прописать? Какую кнопку тнуть? Или как сгенерить из командной строки?
3) Допустим нет у меня idl, как сделать IID из tlb?

Ты не мудри, ты пальцем покажи. (с)
Лучший способ понять что-то самому — объяснить это другому.

keks-n
Доктор VB наук
Доктор VB наук
Аватара пользователя
 
Сообщения: 2509
Зарегистрирован: 19.09.2005 (Пн) 17:17
Откуда: г. Москва

Сообщение keks-n » 08.07.2008 (Вт) 10:07

Antonariy
Ну нет сейчас студии под рукой, а я не помню точно, как это там делается, я обычно, свои tlb когда делаю, получаю 2 заголовка и с ними работаю.
Изображение

Хакер
Телепат
Телепат
Аватара пользователя
 
Сообщения: 16478
Зарегистрирован: 13.11.2005 (Вс) 2:43
Откуда: Казахстан, Петропавловск

Сообщение Хакер » 10.07.2008 (Чт) 0:29

Antonariy
3) OleView (которая в Start-->Programs-->Microsoft Visual Studio 6.0 --> Tools) умеет из TLB восстанавливать дамп на IDL.

по. поводу п.1 и п.2. сказать ничего не могу, т.к. надо читать всё обсуждение, а интернет не позволяет.
—We separate their smiling faces from the rest of their body, Captain.
—That's right! We decapitate them.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 10.07.2008 (Чт) 9:57

С OleView знаком, idl я сам делал, в вопросе написал "допустим". :)

Наверное уже и не надо ничего говорить. Время начинает поджимать, ищем сишника за деньги.
Лучший способ понять что-то самому — объяснить это другому.

Antonariy
Повелитель Internet Explorer
Повелитель Internet Explorer
Аватара пользователя
 
Сообщения: 4824
Зарегистрирован: 28.04.2005 (Чт) 14:33
Откуда: Мимо проходил

Сообщение Antonariy » 15.07.2008 (Вт) 11:42

Чтобы получить IID нужно использовать CLSIDFromString.
В интерфейс добавил процедуру Test. Делаю следующее:
Код: Выделить всё
   IID   iid;
   IDocView *dv;

   HRESULT r = CLSIDFromString(L"{7ADCD0B1-C50E-4A50-80E0-4397F6E5FE7C}", &iid);
   r = CoGetObject(L"DocView.Application",NULL,iid,(void**)&dv);
   _ASSERTE(S_OK != r);

   dv->Test();
Все компилируется, запускается, а на последней строчке вылетает недопустимая операция.
Лучший способ понять что-то самому — объяснить это другому.

Пред.След.

Вернуться в Кирпичный завод

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 5

    TopList