Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041

Создание COM DLL: ошибка в приведении типов

10.07.2015, 18:46. Показов 2055. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Здорова!

Читаю про COM, в книге нашел пример Пример EX24B - обычная MFC DLL, содержащая настоящую COM-версию класса CSpaceship.

Вот код
Файл INTERFACE.h:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
struct IMotion : public IUnknown
{
    STDMETHOD_(void, Fly) ()=0;
    STDMETHOD_(int&, GetPosition) ()=0;
};
 
struct IVisual : public IUnknown
{
    STDMETHOD_(void,Display) ()=0;
};

Файл SPACESHIP.h
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
void ITrace(REFIID iid, const char* str);
 
//////////////////////////////////////////////
//CSpaceship command target
 
class CSpaceship : public CCmdTarget
{
    DECLARE_DYNCREATE(CSpaceship)
 
private:
    int m_nPosition;//доступ к этим переменным возможен из всех интерфейсов
    int m_nAcceleration;
    int m_nColor;
protected:
    CSpaceship();//защищенный конструктор для динамического создания объектов
 
    //Атрибуты
public:
    
    //Операции
public:
 
    //Переопределенные функции
    //переопределенные виртуальные функции, сгенерированные ClassWizard
    //{{AFX_VIRTUAL(CSpaceship)
public:
    virtual void OnFinalRelease();
    //}}AFX_VIRTUAL
 
    //Реализация
protected:
    virtual ~CSpaceship();
 
    //сгенерированные функции таблицы сообщений
    //{{AFX_MSG(CSpaceship)
    //ПРИМЕЧАНИЕ: здесь ClassWizard будет добавлять и удалять функции-члены
    //}}AFX_MSG
 
    DECLARE_MESSAGE_MAP();
    DECLARE_OLECREATE(CSpaceship)
    BEGIN_INTERFACE_PART(Motion,IMotion)
        STDMETHOD_(void,Fly)();
        STDMETHOD_(int&,GetPosition)();
    END_INTERFACE_PART(Motion)
 
    BEGIN_INTERFACE_PART(Visual,IVisual)
        STDMETHOD_(void,Display)();
    END_INTERFACE_PART(Visual)
 
    DECLARE_INTERFACE_MAP()
};
 
//////////////////////////////////////////////////

Файл SPACESHIP.cpp
Кликните здесь для просмотра всего текста
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
#include "stdafx.h"
#include "MfcDllCom.h"
#include "INTERFACE.h"
#include "SPACESHIP.h"
 
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#endif
//////////////////////////////////////////////////
//CSpaceship
 
//{692D03A-C689-11CE-B337-88EA36DE9E4E}
static const IID IID_IMotion=
{0x692d03a4,0xc689,0x11ce,{0xb3,0x37,0x88,0xae,0x36,0xde,0x9e,0x4e}};
 
//{692D0eA5-C689-11CE-B337-88EA36DE9E4E}
static const IID IID_IVisual=
{0x692d03a5,0xc689,0x11ce,{0xb3,0x37,0x88,0xea,0x36,0xde,0x9e,0x4e}};
 
IMPLEMENT_DYNCREATE(CSpaceship,CCmdTarget)
CSpaceship::CSpaceship()
{
    TRACE("Конструктор CSpaceship\n");
    m_nPosition=100;
    m_nAcceleration=101;
    m_nColor=102;
    //чтобы приложение не завершилось, пока активен COM-объект, конструктор вызывает AfxOleLockApp
    AfxOleLockApp();
}
 
CSpaceship::~CSpaceship()
{
    TRACE("ДеструкторCSpaceship\n");
    //чтобы завершить приложение после уничтожения всех созданных COM-объектов,
    //деструктор вызывает AfxOleUnlockApp
    AfxOleUnlockApp();
}
 
void CSpaceship::OnFinalRelease()
{
    //OnFinalRelease вызывается, когда освобождается последняя ссылка на COM-объект
    //Эта реализация уничтожает объект. Добавьте необходимую для вашего объекта очистку
    //перед удалением его из памяти.
 
    delete this;
}
BEGIN_MESSAGE_MAP(CSpaceship,CCmdTarget)
    //{{AFX_MSG_MAP(CSpaceship)
    //ПРИМЕЧАНИЕ: здесь ClassWizard будет добавлять и удалять макросы
    //}}AFX_MSG_MAP
END_MESSAGE_MAP()
 
BEGIN_INTERFACE_MAP(CSpaceship,CCmdTarget)
    INTERFACE_PART(CSpaceship,IID_IMotion,Motion)
    INTERFACE_PART(CSpaceship,IID_IVisual,Visual)
END_INTERFACE_MAP()
 
//(692D03A3-C689-11CE-8337-88FA360E9E4E}
IMPLEMENT_OLECREATE(CSpaceship,"Spaceship",0x692d03a3,0xc689,
    0x11ce,0xb3,0x37,0x88,0xea,0x36,0xde,0x9e,0x4e)
STDMETHODIMP_(ULONG) CSpaceship::XMotion::AddRef()
{
    TRACE("CSpaceship::XMotion::AddRef\n");
    METHOD_PROLOGUE(CSpaceship,Motion)
        return pThis->ExternalAddRef();
}
 
STDMETHODIMP_(ULONG) CSpaceship::XMotion::Release()
{
    TRACE("CSpaceship::XMotion::Release\n");
    METHOD_PROLOGUE(CSpaceship,Motion)
    return pThis->ExternalRelease();
}
 
STDMETHODIMP CSpaceship::XMotion::QueryInterface(REFIID iid, LPVOID* ppvObj)
{
    ITrace(iid, "CSpaceship::XMotion::QueryInterface");
    METHOD_PROLOGUE(CSpaceship,Motion)
    return pThis->ExternalQueryInterface(iid,ppvObj);
}
 
STDMETHODIMP_(void) CSpaceship::XMotion::Fly()
{
    TRACE("CSpaceship::XMotion::Fly\n");
    METHOD_PROLOGUE(CSpaceship,Motion)
    TRACE("m_nPosition=%d\n",pThis->m_nPosition);
    TRACE("m_nAcceleration=%d\n",pThis->m_nAcceleration);
    return;
}
 
STDMETHODIMP_(int&) CSpaceship::XMotion::GetPosition()
{
    TRACE("CSpaceship::XMotion::GetPosition\n");
    METHOD_PROLOGUE(CSpaceship,Motion)
    TRACE("m_nPostion=%d\n",pThis->m_nPosition);
    TRACE("m_nAcceleration=%d\n",pThis->m_nAcceleration);
    return pThis->m_nPosition;
}
/////////////////////////////////////////////
STDMETHODIMP_(ULONG) CSpaceship::XVisual::AddRef()
{
    TRACE("CSpaceship::XVisual::AddRef\n");
    METHOD_PROLOGUE(CSpaceship,Visual)
        return pThis->ExternalAddRef();
}
 
STDMETHODIMP_(ULONG) CSpaceship::XVisual::Release()
{
    TRACE("CSpaceship::XVisual::Release\n");
    METHOD_PROLOGUE(CSpaceship,Visual)
    return pThis->ExternalRelease();
}
 
STDMETHODIMP CSpaceship::XVisual::QueryInterface(REFIID iid, LPVOID* ppvObj)
{
    ITrace(iid,"CSpaceship::XVisual::QueryInterface");
    METHOD_PROLOGUE(CSpaceship,Visual)
    return pThis->ExternalQueryInterface(iid,ppvObj);
}
 
STDMETHODIMP_(void) CSpaceship::XVisual::Display()
{
    TRACE("CSpaceship::XVisual::Display\n");
    METHOD_PROLOGUE(CSpaceship,Visual)
    TRACE("m_nPosition=%d\n",pThis->m_nPosition);
    TRACE("m_nColor=%d\n",pThis->m_nColor);
}
 
/////////////////////////////////////
void ITrace(REFIID iid, const char* str)
{
    OLECHAR* lpszIID;
    ::StringFromIID(iid, &lpszIID);
    CString strTemp=(LPCWSTR) lpszIID;
    TRACE("%s - %s\n",(const char*) strTemp, (const char*) str);
    AfxFreeTaskMem(lpszIID);
}
 
///////////////////////////////
//Обработчики сообщений класа CSpaceship


И когда компилирую получаю ошибки:
Кликните здесь для просмотра всего текста

SPACESHIP.cpp
1>d:\visual studio 2010\projects\mfcdllcom\mfcdllcom\spaces hip.cpp(80): error C2664: CCmdTarget::ExternalQueryInterface: невозможно преобразовать параметр 1 из "const IID" в "const void *"
1> Для выполнения данного преобразования нет доступного оператора преобразования, определенного пользователем, или вызов оператора невозможен
1>d:\visual studio 2010\projects\mfcdllcom\mfcdllcom\spaces hip.cpp(119): error C2664: CCmdTarget::ExternalQueryInterface: невозможно преобразовать параметр 1 из "const IID" в "const void *"
1> Для выполнения данного преобразования нет доступного оператора преобразования, определенного пользователем, или вызов оператора невозможен
1>d:\visual studio 2010\projects\mfcdllcom\mfcdllcom\spaces hip.cpp(136): error C2440: приведение типов: невозможно преобразовать "CString" в "const char *"
1> Для выполнения данного преобразования нет доступного оператора преобразования, определенного пользователем, или вызов оператора невозможен
1>
1>СБОЙ построения.


Как можно перевести const IID в const void* ??? Ошибка в этом коде:
C++
1
2
3
4
5
6
STDMETHODIMP CSpaceship::XMotion::QueryInterface(REFIID iid, LPVOID* ppvObj)
{
    ITrace(iid, "CSpaceship::XMotion::QueryInterface");
    METHOD_PROLOGUE(CSpaceship,Motion)
    return pThis->ExternalQueryInterface(iid,ppvObj);//в этой строк нужно преобразовать.
}
???????

Добавлено через 4 часа 42 минуты
Ну так что? Кто этот пример разбирал? В книге там этот пример для VS6, а я набрал его в VS10, мб. из за этого ошибки вылазят?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
10.07.2015, 18:46
Ответы с готовыми решениями:

Ошибка в приведении типов
Здравствуйте. Я недавно начал самостоятельно изучать программирование Win32 приложений, и у меня стабильно возникает похожая ошибка:...

О приведении типов и классов
Читая про приведение типов из msdn наткнулся на фразу Этого я, признаюсь, не понял. Производные классы имеют все те же поля и методы,...

Ну жна помощь в приведении типов
Никак не могу понять как работает приведение типов. В первую очередь про dynamic_cast. Допустим у нас есть такая часть программы ...

6
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
13.07.2015, 20:27  [ТС]
В общем исправил эту ошибку, там нужно указатель передавать отак:
C++
1
return pThis->ExternalQueryInterface(&iid,ppvObj);
Но появилась другая ошибка:
1>ClCompile:
1> Для всех выходных данных обновления не требуется.
1> SPACESHIP.cpp
1>d:\visual studio 2010\projects\mfcdllcom\mfcdllcom\spaces hip.cpp(136): error C2440: приведение типов: невозможно преобразовать "CString" в "const char *"
1> Для выполнения данного преобразования нет доступного оператора преобразования, определенного пользователем, или вызов оператора невозможен
1>
1>СБОЙ построения.

ошибка в этой функции:
C++
1
2
3
4
5
6
7
8
9
/////////////////////////////////////
void ITrace(REFIID iid, const char* str)
{
    OLECHAR* lpszIID;
    ::StringFromIID(iid, &lpszIID);
    CString strTemp=(LPCWSTR) lpszIID;
    TRACE("%s - %s\n",(const char*)strTemp, (const char*) str);
    AfxFreeTaskMem(lpszIID);
}
не может преобразовать CString strTemp в (const char*), почему не может преобразоваться???? В настройках выставлено использовать кодировку юникод, когда выставляю использовать многобайтную кодировку, то преобразовывается, но появляется другая ошибка уже в этой строчке CString strTemp=(LPCWSTR) lpszIID;, тут оно не может преобразовать LPCWSTR в CString.
Как эту ошибку обойти? Я пока закоментировал строку с ошибкой и так скомпелировал и получил COM DLL, а теперь что с этим COM DLL делать?

Добавлено через 1 минуту
Создал объект DLL COM теперь нужно его как то попытаться использовать но как? ))))

Добавлено через 41 минуту
Я создал тестовый пример и сейчас у меня пишет ошибки:
Не найден Program ID -- ошибка = 800401f3
То есть он не может найти в реестре найти GUID моей COM DLL, как добавить в реестр свою COM???

Добавлено через 6 минут
Как добавить в реестр информацию о MFC COM DLL?

Добавлено через 20 минут
Так что никто не знает как его зарегистрировать? Я добавил dll в windows/system32 и вызвал из меню пуск -> выполнить regsvr32 MfcDllCom.dll , и у меня выводится ошибка:


Добавлено через 1 минуту
в книге написано что для того чтобы зарегистрировать dll нужно использовать использовать специальную утилиту с диска под названием REGCOMP где ее брать хз.
0
694 / 304 / 99
Регистрация: 04.07.2014
Сообщений: 851
13.07.2015, 20:50
Зачем тебе com? Брось каку.
0
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
14.07.2015, 08:57  [ТС]
Цитата Сообщение от AlexVRud Посмотреть сообщение
Зачем тебе com? Брось каку.
ЧЕ?

Добавлено через 3 минуты
Нашел утилиту RegComp и все рамно она не регистрирует, пишет ошибку:
failed to find dllregisterserver function что делать? что это означает?

Добавлено через 9 минут
Ну так что это значает, не может найти dllRegisterServer, а что это такое?

Добавлено через 10 часов 0 минут
так что никто не знает как зарегистрировать COM компонент?

Добавлено через 30 минут

и что делать? как исправлять?

Добавлено через 37 секунд
Я смотрел что эта ошибка означает, это типо у меня неправильный dll. А что делать? как его исправлять?
0
694 / 304 / 99
Регистрация: 04.07.2014
Сообщений: 851
14.07.2015, 10:05
Ну а почитать внимательно про процесс создания com-объектов кто будет? Надо не только написать класс. Но и описать интерфейс, сгенерировать прослойку и откомпилить уже все вместе. Ты для начала подбери побольше литературы и найди простой пример.
З.Ы.: если ты сейчас не знаешь зачем тебе com объекты и с чем их едят. Начни с чего-то более простого. Прочитай про REST, ZeroMQ и Т.п.
0
 Аватар для ninja2
979 / 196 / 33
Регистрация: 26.09.2012
Сообщений: 2,041
14.07.2015, 10:16  [ТС]
Цитата Сообщение от AlexVRud Посмотреть сообщение
Прочитай про REST, ZeroMQ и Т.п.
Ачто это такое? Мне нужно COM и ActiveX разобрать, я хочу в своих программах использовать уже готовые программы и не заморачиватся.
Кстати только что "методом тыка" заработало, зарегистрировал dll и все заработало, проблема была в самой dll, там ее нужно создавать как dll, а я как попало создал

Хороше бы еще рассмотреть пример с COM EXE, с dll разобрались, а как создать теперь COM exe - так называемый внешний компонент. dll это как бы внутренний компонент, а exe внешний.

Да тут еще где на диске должны хранится COM компоненты? От например COM DLL как я понял ее как обычную dll в папке с программой не получится сохранять, ее же ведь нужно регистрировать? Значит что получается ее нужно в windows/system32 закидывать, регистрировать и потом использовать? Вообще то я не пробовал ее запустить из папки программы, но что то мне кажется что из папки программы оно не будет работать, от если я удалю зарегистрированую COM dll из system32 и скопирую ее в папку с программой, то она ж не найдется правильно? Щас проверю

Добавлено через 57 секунд
Цитата Сообщение от AlexVRud Посмотреть сообщение
З.З.Ы.: и ещё, для твоего вопроса есть отдельная ветка https://www.cyberforum.ru/com-ole/
Я не хочу в этой ветке создавать, там людей мало, само больше в С++ для начинающих. Там создай и будешь ждать год пока кто то ответит

Добавлено через 8 минут
Цитата Сообщение от ninja2 Посмотреть сообщение
Щас проверю
Только проверил, удаляю из syste32 и добавляю в папку с программой и не работает, что так оно и должно быть, а почему dll работают? Получается нужно повторно регистрировать dll уже из папки с программой тогда работает.
0
Модератор
 Аватар для vxg
3409 / 2180 / 354
Регистрация: 13.01.2012
Сообщений: 8,450
14.07.2015, 10:51
Цитата Сообщение от ninja2 Посмотреть сообщение
а почему dll работают?
потому что DLL грузит система: при загрузке EXE система находит в нем информацию о том какие DLL и какие функции он использует и загружает эти DLL / получает точки входа в функции (если загрузка не производится "руками" и указано только имя DLL, то в начале поиск DLL идет в папке с EXE затем в системной папке - почему? - так сделали).
DLL в котором живет COM-объект так же загружает система. но причина этой загрузки не запуск EXE, а создание объекта - кто-то где-то в системе создает объект определенного класса, система ищет в реестре запись в которой написано где лежит DLL в котором живет этот объект (запись создается при регистрации), загружает ее и получает от нее ссылку на объект. если вы утащили DLL, то система конечно же не найдет ее.
напрасно вы игнорируете ветку форума посвященную COM - да, в ветке для начинающих больше людей, но и вопрос ваш утонет в потоке проблем-однодневок. больные вашей проблемой люди заходят в соответствующую ветку, а другие вам вряд ли ответят.
пример COM (без обложек) https://www.cyberforum.ru/com-... ost3538077
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
14.07.2015, 10:51
Помогаю со студенческими работами здесь

FormatException не обработано при приведении типов
Надоело, просто жесть как надоело: err = Convert.ToInt32(hgg); ferrors = err; Ну что здесь не правильно? Студия...

Изменение значения при приведении типов
Привет форумчане! Вот часть программы: u = 64000; s = (short) u; console.Writeline("s после присвоения 64000: " + u +...

Нахождение ошибки в наследовании и приведении типов
имеется рабочий код на с++, пыталась переделать его в С#, возникают ошибки,которые я не в состоянии сама исправить. Буду безумно...

Почему выдает ошибку о приведении типов?
{$reference System.Windows.Forms.dll} {$reference System.Drawing.dll} uses System.Windows.Forms; type Form =...

Куда деваются байты при приведении типов?
Всем доброго времени суток... Т.к. основной проект на c++, то пишу сюда... Непонятки с приведением типов, объясните пожалуйста... ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

Новые блоги и статьи
SDL3 для Web (WebAssembly): Работа со звуком через SDL3_mixer
8Observer8 08.02.2026
Содержание блога Пошагово создадим проект для загрузки звукового файла и воспроизведения звука с помощью библиотеки SDL3_mixer. Звук будет воспроизводиться по клику мышки по холсту на Desktop и по. . .
SDL3 для Web (WebAssembly): Основы отладки веб-приложений на SDL3 по USB и Wi-Fi, запущенных в браузере мобильных устройств
8Observer8 07.02.2026
Содержание блога Браузер Chrome имеет средства для отладки мобильных веб-приложений по USB. В этой пошаговой инструкции ограничимся работой с консолью. Вывод в консоль - это часть процесса. . .
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru