|
8 / 3 / 1
Регистрация: 11.08.2016
Сообщений: 46
|
|||||||||||||||||||||||||||||||
Простой пример создания COM компонента15.04.2021, 09:59. Показов 20329. Ответов 8
Доброго времени суток! В универе по системному программированию дали лабу: написать либу с COM-компонентом и программу, которая бы ее использовала. Не могу никак разобраться, как грамотно, нормально написать простой COM-компонент. В теории я вроде бы разобрался, но на практике ничего не выходит.
На MSDN я нашел пример "простого" COM-компонента с использованием WinRT (https://docs.microsoft.com/ru-... -coclasses), но из того кода я ничего не понял - мои знания C++ на уровне "Си + ООП от C#". Нагуглив несколько старых статей в интернете... 1) https://www.rsdn.org/article/com/introcom.xml 2) http://www.comprice.ru/article... p?ID=42510 ...я сумел кое-что написать (библиотеку) и это даже скомпилилось) А вот клиент не компилится. XD Но проблема еще и в том, что я не могу понять, как теперь эту библиотеку использовать: .lib-файл не создается (т.к., насколько я понимаю, нет ни одной переменной, которая бы содержала __declspec(dllexport) ). Объясните, пожалуйста, как решить эту проблему, где у меня ошибки. На данный момент я в тупике, ощущение, что сделал неправильно все, что можно было) XD Но хочу разобраться. Когда .lib-файл не создался, я попробовал добавить DllExport везде, где можно, но само собой это не сработало) БИБЛИОТЕКА framework.h - тут ничего интересного, но все же скину для полноты картины Кликните здесь для просмотра всего текста
CA.h Кликните здесь для просмотра всего текста
IX.h Кликните здесь для просмотра всего текста
IY.h Кликните здесь для просмотра всего текста
CA.cpp Кликните здесь для просмотра всего текста
Еще есть pch.h и pch.cpp, но их показывать нет смысла. КЛИЕНТ В клиенте VS жалуется на строки 16, 30 и 43. Этот пример я взял из интернета. Кликните здесь для просмотра всего текста
Надеюсь, кто-нибудь сможет грамотно объяснить, как это работает и как все соединить. Заранее спасибо!
0
|
|||||||||||||||||||||||||||||||
| 15.04.2021, 09:59 | |
|
Ответы с готовыми решениями:
8
простой пример использования компонента TrackBar Простой пример создания нового потока с интерфейсом Runnable Привидите простой пример создания Dll файла, но чтобы в самом Dll находился файл. |
|
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,097
|
||
| 15.04.2021, 18:07 | ||
|
1
|
||
|
Модератор
3407 / 2178 / 354
Регистрация: 13.01.2012
Сообщений: 8,448
|
|
| 16.04.2021, 13:57 | |
|
0
|
|
|
8 / 3 / 1
Регистрация: 11.08.2016
Сообщений: 46
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| 30.04.2021, 21:05 [ТС] | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Компонент "по классике жанра" - MathComponent, но с двумя интерфейсами (+ и -, * и /). Проблемы: 1) Клиент вылетает почти в самом конце при вызове
3) По диаграмме последовательности COM, которую я прикрепил, видно, что у нас должна быть возможность получить один интерфейс компонента через другой, но почему-то я так сделать не могу - функции QueryInterface в моем интерфейсе нет, хотя они и наследуются от IUnknown. Клиент: Кликните здесь для просмотра всего текста
Библиотека: Laba4COM.def Кликните здесь для просмотра всего текста
pch.h Кликните здесь для просмотра всего текста
Laba4COM.cpp Кликните здесь для просмотра всего текста
Math.h Кликните здесь для просмотра всего текста
Math.cpp Кликните здесь для просмотра всего текста
MathClassFactory.h Кликните здесь для просмотра всего текста
MathClassFactory.cpp Кликните здесь для просмотра всего текста
registration.h Кликните здесь для просмотра всего текста
registration.cpp Кликните здесь для просмотра всего текста
0
|
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,097
|
||
| 01.05.2021, 00:38 | ||
|
IAdder и IMultiplier - это два экспортируемых из библиотеки интерфейса (кода вы не дали, но я так предполагаю). Math - это уже не интерфейс, это внутренний библиотечный класс, реализующий оба вышеозначенных интерфейса. Это весьма спорное решение и, как видно из вашего кода, вы не совсем понимаете, что с этим нужно делать дальше. Самым простым и наглядным примером было бы написать две разные реализации интерфейсов, одну для IAdder, вторую для IMultiplier. Добавить ещё два GUID-а, по одному на каждый интерфейс. Из клиента создать интерфейсы двумя вызовами CreateInstance с указанием соответствующих GUID-ов. Каждый вызов CreateInstance будет создавать новый объект реализующий соответствующий интерфейс. Два интерфейса - два объекта. Если же вы решили делать один объект, который будет поддерживать два интерфейса, то нужно писать соответствующий обработчик QueryInterface, который будет грамотно преобразовывать указатель на this. На разные клиентские запросы нужно возвращать (IAdder*)this или (IMultiplier*)this. Общие замечания к вашему коду. 1) #include "Math.h" внутри клиента - это нонсенс, как и преобразование ((Math*)pAdder). Клиент оперирует только интерфейсами и GUID-ами. 2) Каждый QueryInterface требует последующего вызова Release. Вы дважды в клиентском коде запрашиваете интерфейсы и только один раз делаете освобождение.
0
|
||
|
8 / 3 / 1
Регистрация: 11.08.2016
Сообщений: 46
|
|||||||||||||||||||||
| 02.05.2021, 23:32 [ТС] | |||||||||||||||||||||
|
IAdder.h Кликните здесь для просмотра всего текста
IMultiplier.h Кликните здесь для просмотра всего текста
Буду дальше исправлять косяки, большое спасибо! Добавлено через 17 минут Math.cpp Кликните здесь для просмотра всего текста
Но как быть с вызовом Release()? Я понимаю, что приводить тип интерфейса к типу класса Math для вызова Release() - полный бред, но что нужно исправить, чтобы можно было из самого интерфейса вызывать функцию? Вот это я понять никак не могу...(
0
|
|||||||||||||||||||||
|
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,097
|
||
| 03.05.2021, 10:16 | ||
Сообщение было отмечено Ivanshka как решение
РешениеЗапросили интерфейс сложения, поработали с ним - сделайте его освобождение. Запросили интерфейс умножения, поработали с ним - сделайте его освобождение. Что такое интерфейс? Интерфейс - это табличка в памяти, которая содержит адреса всех функций перечисленных в описании интерфейса. Получая интерфейс - вы получаете указатель на начало соответствующей таблички. Вызовы функций интерфейса выполняются через вызовы адресов из таблички. Класс, который наследуется от интерфейса, содержит в себе помимо переменных ещё и табличку функций интерфейса. Это значит, что когда вы создаёте экземпляр класса, то выделяется память, в которой размещаются все переменные класса и табличка виртуальных функций. Когда вы переопределяете виртуальную функцию на новую, то её новый адрес помещается в старую табличку. Если же вы решили сделать класс, который наследуется от двух интерфейсов, то внутри такого класса размещаются две таблички функций, по одной на каждый интерфейс. Именно к этим табличкам вы приводите указатель this, когда клиент запрашивает соответствующие интерфейсы. Каждый ваш интерфейс ещё унаследован от IUnknown. Это означает, что табличка функций интерфейса содержит как собственные функции, так и функции базового интерфейса. Как я уже говорил, при создании класса, который наследуется от двух ваших интерфейсов, получаются две таблички функций. Каждая табличка будет содержать три функции IUnknown. Нужно, что бы функции IUnknown каждой таблички ссылались на общую реализацию сделанную для класса. Тогда не важно какой интерфейс вы освобождаете, всё равно должна быть вызвана единая общая функция. Добавлено через 50 минут Наврал малость по табличкам, но не принципиально. В экземпляре класса хранится не сама табличка, а адрес таблички. Важно, что нужно вызывать единую функцию Release (AddRef, QueryInterface). А в разных табличках интерфейсов одного класса могут быть указаны одинаковые адреса функций.
2
|
||
|
8 / 3 / 1
Регистрация: 11.08.2016
Сообщений: 46
|
|||||||||||||
| 09.05.2021, 16:55 [ТС] | |||||||||||||
Только так я могу вызывать его функции в клиенте. Что касается теории по интерфейсам, то это я знаю, и все же спасибо - освежил память) :-) Теперь я до конца понял, как что делать, и все работает. Большое спасибо за помощь!) Добавлено через 30 минут Кликните здесь для просмотра всего текста
0
|
|||||||||||||
|
2734 / 888 / 331
Регистрация: 10.02.2018
Сообщений: 2,097
|
||
| 11.05.2021, 11:12 | ||
|
Могу сделать пару замечаний, но они скорее косметические. 1. MathClassFactory, это стандартный интерфейс фабрики. Инклудить его имеет смысл только ради CLSID. С другой стороны, вы явно определяете в коде клиента CLSID_Math. Получается некоторая избыточность, нужно либо одно, либо другое. Обычно GUID-ы подключают инклудами, а не копипастой констант. 2. Я ни разу не встречал создание интерфейса/объекта через запрос IID_IUnknown (37 строка). Обычно есть имя интерфейса и к нему прилагается два GUID-а: CLSID_<имя интерфейса> и IID_<имя интерфейса>. 3. Я не встречал ручное создание фабрики. Для создания интерфейса обычно используется CoCreateInstance. Эта функция сама создает фабрику, создает фабрикой объект и удаляет фабрику. Такой алгоритм создания объектов универсален, нет смысла каждый раз заново прописывать лишний однотипный код в новом приложении.
0
|
||
| 11.05.2021, 11:12 | |
|
Помогаю со студенческими работами здесь
9
Простой вариант дублирования компонента Пример внешенего компонента на Delphi
Ошибка создания компонента Проблема создания компонента Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ВВЕДЕНИЕ
Введу сокращения:
аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
|
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi
ветка по-частям.
коммит Create переделка под биомассу. txt
вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
|
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ *
Дана цепь постоянного тока с сопротивлениями и напряжениями. Надо найти токи в ветвях.
Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и решает её.
Последовательность действий:. . .
|
Новый CodeBlocs. Версия 25.03
palva 04.01.2026
Оказывается, недавно вышла новая версия CodeBlocks за номером 25. 03. Когда-то давно я возился с только что вышедшей тогда версией 20. 03. С тех пор я давно снёс всё с компьютера и забыл. Теперь. . .
|
|
Модель микоризы: классовый агентный подход
anaschu 02.01.2026
Раньше это было два гриба и бактерия. Теперь три гриба, растение.
И на уровне агентов добавится между грибами или бактериями взаимодействий.
До того я пробовал подход через многомерные массивы,. . .
|
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Налог на собак: https:/ / **********/ gallery/ V06K53e
Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf
Пост отсюда. . .
|
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop?
Ниже её машинный перевод.
После долгих разбирательств я наконец-то вернула себе. . .
|
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод
Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод.
Thinkpad X220 Tablet —. . .
|