Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.88/8: Рейтинг темы: голосов - 8, средняя оценка - 4.88
-23 / 4 / 0
Регистрация: 15.08.2014
Сообщений: 492

Как использовать DLL (СОМ-объект) без регистрации (фильтр DirectShow)

28.05.2022, 21:34. Показов 1672. Ответов 6
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Я хочу подключить фильтр к графу DirectShow без регистрации DLL, в которой реализован фильтр (COM-объект).
Прочитал статью, в которой предлагается способ. код приведен ниже - последние строки собственно и подключают фильтр к графу.

Может мне кто-нибудь объяснить как работает строка (внизу), т.е. корректна ли она :
IBaseFilterPtr pFilter = pUnk ?

Насколько я понимаю pUnk - это указатель на IUnknown, т.е. тип не соответствует типу pFilter.

У меня она не компилируется (IBaseFilterPtr я заменил на IBaseFilter*, а IUnknownPtr на IUnknown*, т.к. не нашел этих типов в примере, но по логике это должны быть такие определения).

Когда пробовал у себя провернуть то же самое, использовал IBaseFilter* pFilter = (IBaseFilter*) pUnk,
то AddFilter "вылетал" с ошибкой - из чего я делаю вывод, что мое приведение типов некорректно.

Мой вопрос: каким образом получить из pUnk корректный указатель на фильтр, чтобы добавить его к графу ?

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
// define the prototype of the class factory entry point in a COM dll
typedef HRESULT (STDAPICALLTYPE* FN_DLLGETCLASSOBJECT)(REFCLSID clsid, REFIID iid, void** ppv);
 
HRESULT CreateObjectFromPath(TCHAR* pPath, REFCLSID clsid, IUnknown** ppUnk)
{
    // load the target DLL directly
    HMODULE lib = LoadLibrary(pPath);
    if (!lib)
    {
        return HRESULT_FROM_WIN32(GetLastError());
    }
 
    // the entry point is an exported function
    FN_DLLGETCLASSOBJECT fn = (FN_DLLGETCLASSOBJECT)GetProcAddress(lib, "DllGetClassObject");
    if (fn == NULL)
    {
        return HRESULT_FROM_WIN32(GetLastError());
    }
 
    // create a class factory
    IUnknownPtr pUnk;
    HRESULT hr = fn(clsid,  IID_IUnknown,  (void**)(IUnknown**)&pUnk);
    if (SUCCEEDED(hr))
    {
        IClassFactoryPtr pCF = pUnk;
        if (pCF == NULL)
        {
            hr = E_NOINTERFACE;
        }
        else
        {
            // ask the class factory to create the object
            hr = pCF->CreateInstance(NULL, IID_IUnknown, (void**)ppUnk);
        }
    }
 
    return hr;
}
...................................................
IUnknownPtr pUnk;
HRESULT hr = CreateObjectFromPath(TEXT("c:\\path\\to\\myfilter.dll"), IID_MyFilter, &pUnk);
if (SUCCEEDED(hr))
{
    IBaseFilterPtr pFilter = pUnk;
    pGraph->AddFilter(pFilter, L"Private Filter");
    pGraph->RenderFile(pMediaClip, NULL);
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
28.05.2022, 21:34
Ответы с готовыми решениями:

Как использовать ActiveX без регистрации
Привет! Моя прога использует один ActiveX-контрол и я не хочу регистрировать его под WinXP. Возможно ли использовать ActiveX без...

Как использовать COM-объект (dll)
Пытаюсь разобраться с COM-объектами на C#. Решил начать с "Hello world!", но это оказалось совсем не так просто, как я думал. Понял что...

DirectShow как добавить фильтр?
Есть замечательная статья про DirectShow в C#. Там же есть исходники и скомпилированные примеры. Среди примеров есть DxPlayer, который...

6
COM‐пропагандист
 Аватар для Замабувараев
936 / 785 / 149
Регистрация: 18.12.2014
Сообщений: 2,256
Записей в блоге: 4
28.05.2022, 23:02
Например, вы можете запросить нужный вам интерфейс у вашего пУньк через метод QueryInterface. Может быть что‐то вроде такого:

C
1
2
3
4
5
6
7
IBaseFilter *pFilter;
HRESULT hr = pUnk->lpVtbl->QueryInterface(pUnk, &IID_IBaseFilter, &pFilter);
 
if(FAILED(hr))
{
    // обработка ошибки — не может получить интерфейс
};
Добавлено через 14 минут
Если вы делаете COM DLL, то такая библиотека должна быть оформлена по всем правилам COM, то есть должна иметь экспортируемые функции вроде DllGetClassObject и DllCanUnloadNow.

Ну а если вы просто создаёте свою реализацию интерфейса IBaseFilter, то можете обойтись без DLL, просто подсовывать указатель на вашу реализацию интерфейса IBaseFilter куда просят.

Добавлено через 12 минут
Цитата Сообщение от LUN2 Посмотреть сообщение
HRESULT hr = CreateObjectFromPath(TEXT("c:\\path\\to\ \myfilter.dll"), IID_MyFilter, &pUnk);
Ну и тут должно передаваться не IID_MyFilter, а CLSID_MYFILTER.
0
-23 / 4 / 0
Регистрация: 15.08.2014
Сообщений: 492
29.05.2022, 23:00  [ТС]
спасибо за ответ.

Еще прошу подсказать по созданию собственного интерфейса для COM-объекта.
Я взял из SDK пример фильтра DUMP к DirectShow и решило добавить свой интерфейс.
мои шаги по дббавлению интерфейса:

1) В определение COM-объекта (CDump) добавляем свой интерфейс IMyInterface

C++
1
2
3
4
5
6
7
8
//  CDump object which has filter and pin members
class CDump : public CUnknown, public IFileSinkFilter, public IMyInterface
{
    friend class CDumpFilter;
    friend class CDumpInputPin;
 
    CDumpFilter   *m_pFilter;       // Methods for filter interfaces
    CDumpInputPin *m_pPin;          // A simple rendered input pin

2) Объявляем свой интерфейс IMyInterface

C++
1
2
3
4
5
6
7
8
9
10
DEFINE_GUID(IID_MyInterface,
    0x11b86ee6, 0x8d30, 0x46ea, 0xb1, 0x82, 0xea, 0xd1, 0x85, 0xd, 0x50, 0x3e);
 
class IMyInterface : public IUnknown {
 
public:
    HRESULT STDMETHODCALLTYPE Test1() {return 1;};
 
    HRESULT STDMETHODCALLTYPE Test2() = 0 {return 2;};
};

3) Возврат ссылки на наш интерфейс:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
//
// NonDelegatingQueryInterface
//
// Override this to say what interfaces we support where
//
STDMETHODIMP CDump::NonDelegatingQueryInterface(REFIID riid, void ** ppv)
{
    CheckPointer(ppv,E_POINTER);
    CAutoLock lock(&m_Lock);
 
    // Do we have this interface
 
    if (riid == IID_MyInterface) {
        return GetInterface((IMyInterface*)this, ppv);
    }
    else
В результате, когда я запрашиваю этот интерфейс, получаю сообщение об его отсутствии:

C++
1
2
3
4
           // Получаем наш интерфейс для обмена данными с фильтром
            IDumpInterface* pDumpInterface;
            hr5 = pUnk->QueryInterface(IID_DumpInterface, (void**)&pDumpInterface);
            std::cout << "Query our DUMP interface. Result = " << hr5 << std::endl;
hr==E_NOINTERFACE...

Навскидку, не пропустил ли я каких-то важных шагов при создании интерфейса ?
0
COM‐пропагандист
 Аватар для Замабувараев
936 / 785 / 149
Регистрация: 18.12.2014
Сообщений: 2,256
Записей в блоге: 4
29.05.2022, 23:09
Цитата Сообщение от LUN2 Посмотреть сообщение
2) Объявляем свой интерфейс IMyInterface
А почему у вас реализация внутри интерфейса? Интерфейс должен быть чисто виртуальным и полностью абстрактным классом.
Реализацию пишите в своём производном классе.

Добавлено через 2 минуты
Цитата Сообщение от LUN2 Посмотреть сообщение
hr5 = pUnk->QueryInterface(IID_DumpInterface, (void**)&pDumpInterface);
Не вижу где вы запрашиваете IID_MyInterface.
Вы запрашиваете IID_DumpInterface, который вы точно реализовали и объявили, что его поддерживаете в QueryInterface?
0
-23 / 4 / 0
Регистрация: 15.08.2014
Сообщений: 492
29.05.2022, 23:30  [ТС]
Прошу прощения, что ввел в заблуждение, переименовывал гуиды - было IID_MyInterface, заменено на другое имя:
C++
1
2
3
4
5
6
7
8
9
10
11
12
// Интерфейс для взаимодействия основной программы с фильтром
// {11B86EE6-8D30-46EA-B182-EAD1850D503E}
DEFINE_GUID(IID_DumpInterface,
    0x11b86ee6, 0x8d30, 0x46ea, 0xb1, 0x82, 0xea, 0xd1, 0x85, 0xd, 0x50, 0x3e);
 
class IMyInterface : public IUnknown {
 
public:
    HRESULT STDMETHODCALLTYPE Test1() {return 1;};
 
    HRESULT STDMETHODCALLTYPE Test2() = 0 {return 2;};
};
т.е. QueryInterface запрашивает интерфейс с ИД = IID_DumpInterface, как и должно быть.


В части Вашего замечания о виртуальности класса - возможно это не соответствует теоретическому подходу - сделано исключительно для упрощения, это изменю, а разве это может повлиять на опознаваемость наличия интерфейса ?
У меня сейчас проблема именно в этом.

Добавлено через 4 минуты
Еще после ввсего этого я нашел примеры объявления своего интерфейса - см. ниже.

Я не использовал макрос DECLARE_INTERFACE_ (честно говоря, еще не изучил этот вопрос).

Может Вы подскажете - неиспользование такого шаблона может ли быть причиной, что интерфейс не опознан ?

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


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
DECLARE_INTERFACE_(IIPEffect, IUnknown)
{
    STDMETHOD(get_IPEffect) (THIS_
                int *effectNum,         // The current effect
                REFTIME *StartTime,     // Start time of effect
                REFTIME *Length         // length of effect
             ) PURE;
 
    STDMETHOD(put_IPEffect) (THIS_
                int effectNum,          // Change to this effect
                REFTIME StartTime,      // Start time of effect
                REFTIME Length          // Length of effect
             ) PURE;
};
0
COM‐пропагандист
 Аватар для Замабувараев
936 / 785 / 149
Регистрация: 18.12.2014
Сообщений: 2,256
Записей в блоге: 4
30.05.2022, 00:22
Цитата Сообщение от LUN2 Посмотреть сообщение
GetInterface((IMyInterface*)this, ppv)
Очевидно, что эта функция не срабатывает как надо. Но обычно встречается что‐то вроде такого:
C++ (Qt)
1
*ppv = (IВашИнтерфейс*) this
1
-23 / 4 / 0
Регистрация: 15.08.2014
Сообщений: 492
30.05.2022, 21:22  [ТС]
Спасибо за подсказки.
Нашел в чем ошибка, к счастью - это исключительно мой недосмотр, а не по причине несоблюдения методологии COM.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
30.05.2022, 21:22
Помогаю со студенческими работами здесь

Как использовать dll, без её функций
Добрый вечер. По примеру я создал библиотеку, которая добавляет в системное меню некоторые пункты с вложением(типа контексное). Проблема...

Как создать фильтр для DirectShow в Delphi?
Дошел до создания фильтров в DirectShow, Теории достаточно с этим проблем нет, а вот с созданием есть. Заголовочные файлы я нашел, вроде...

Взаимодействие exe64 с dll32. COM объект без регистрации в реестре
добрый вечер. windows7 (или выше), visual studio 2013, c++ есть 64 битное приложение (для простоты пусть будет обычное...

Prolog как СОМ-объект (windows)
Есть ли реализации пролога как COM объекта?

Использовать ли Directshow, или лучше как-то по-другому
Я не программист, так что сильно не ругайтесь. Задача такая: Отобразить видео нестандартного формата. Если бы поток был скажем...


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

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru