|
Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » [решено] *DirectX* | DShow и С++, проблема с линковкой программ |
|
[решено] *DirectX* | DShow и С++, проблема с линковкой программ
|
Ветеран Сообщения: 3320 |
Кто работать с библиотеками ДиректХ (в особености DirectShow) из под С/С++?
Под Делфи 6/7 всё гладко проходит. Начал писать под С++ (среда Visual Studio 6.0), однако сразу напоролса на сложности. Проект компилируется, а при попитке получить ЕХЕ линковщик сбоит error LNK2001 unresolved external symbol. Хотя текст файл официально опубликован на Микрософт Спасибо за внимание. P/S Вот сам код где пробуем играть видео файл посредство DShow в среде С++ #include <dshow.h> void main(void) { IGraphBuilder *pGraph = NULL; IMediaControl *pControl = NULL; IMediaEvent *pEvent = NULL; // Initialize the COM library. HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { printf("ERROR - Could not initialize COM library"); return; } // Create the filter graph manager and query for interfaces. hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph); if (FAILED(hr)) { printf("ERROR - Could not create the Filter Graph Manager."); return; } hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); // Build the graph. IMPORTANT: Change this string to a file on your system. hr = pGraph->RenderFile(L"C:\\Example.avi", NULL); if (SUCCEEDED(hr)) { // Run the graph. hr = pControl->Run(); if (SUCCEEDED(hr)) { // Wait for completion. long evCode; pEvent->WaitForCompletion(INFINITE, &evCode); // Note: Do not use INFINITE in a real application, because it // can block indefinitely. } } pControl->Release(); pEvent->Release(); pGraph->Release(); CoUninitialize(); } |
|
Отправлено: 01:55, 01-02-2006 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Admiral
Эта ошибка означает, что компилятор не находит реализацию (т.е. непосредственно точку входа в объектном коде) какой-то из использованных функций. Все WinAPI функции, конечно реализованны в соответствующих системных .dll, но компилятор то об этом не знает и даже не умеет напрямую из dll функции импортировать (вернее, раньше не умел, а сейчас с помощью специальных прагм это возможно, вроде. Но нестандартно совсем). Поэтому создаются специальные .lib-заглушки для системных вызовов. Наиболее часто используемые обычно добавляются IDE в проект при его создании автоматически. Я бы поставил на то, что у вас не подключена к проекту ole32.lib, в которой находятся заглушки для CoCreateInstance и иже с ним. Но точно можно будет сказать, если вы приведёте весь текст ошибки, где указывается в том числе и не найденное имя, а по имени уже можно найти и библиотеку соответствующую. |
------- Отправлено: 16:08, 01-02-2006 | #2 |
Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети. Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля. |
Ветеран Сообщения: 3320
|
Профиль | Отправить PM | Цитировать ivank
Спасибо за ответ. Теперь стало понятно где искать проблему. Цитата:
Цитата:
А на счёт Цитата:
main.obj : error LNK2001: unresolved external symbol _IID_IVideoWindow main.obj : error LNK2001: unresolved external symbol _IID_IMediaControl main.obj : error LNK2001: unresolved external symbol _CLSID_FilterGraph main.obj : error LNK2001: unresolved external symbol _IID_IGraphBuilder Я полагаю что опытный сишних ориентируэтса где в какой бибилиотеке что прописано... А начальный? Мануалы читать? А какой оператор можно использовать в коде для подключения библиотек (что б было видно непосредственно, а не так через Project->Settings (ALT+F7))? И почему при добавлении /stack:0x200000,0x200000 /subsystem:windows /machine:I386 /ignore:4089 /ignore:4078 в Project Options выдайотса аналогичная ошибка ? Р.S Спасибо за вступительную теорию. А то я сомневался, что MSVS 6.0 весь битый и ничего путёвого в нём реально не напишиш (напишеш но не получиш ЕХЕ). В Делфи как то проше, но для системных прог С++, как мне кажетса, лутше предназначен. |
|||
Последний раз редактировалось Admiral, 02-02-2006 в 03:33. Отправлено: 22:39, 01-02-2006 | #3 |
редкий гость Сообщения: 1696
|
Профиль | Сайт | Отправить PM | Цитировать Во-первых, моё предположение всё таки оказалось ложным. Т.к. не найдена была не функция, а экспортируемые переменные. Поскольку гуиды по сути своей шестнадцатибайтные стркутуры, то им надо где-то храниться. Хранят и задают значение _одному_ экземпляру структуры, которй описан/хранится в соответствующем объектном модуле (библиотеке в данном случае), в остальных местах на него тольок _ссылаются_. Поэтому если не слинковать программу с соответствующим файлом, то эти ссылки останутся ни к чему не привязанными, что и произошло. Опять же с помощью расшерений MSVC можно приписать IID/GUID прямо к интерфейсу в месте его описания. Что не есть стандартно.
Цитата:
Цитата:
Цитата:
Цитата:
В принципе можно выделить два типа приложение - консольные и windows. Первые это /subsystem:console. При этом линкер создаёт точку входа в программу, в которой инициализируются стандартные библиотеки, включая ввод-вывод на консоль (наверное, консоль тоже создаётся заодно) и затем вызывается функция main. Второй тип приложений - windows приложения. /subsystem:windows. При этом линкером создаётся точка входа в программу, в которой то же что-то инициализируется и затем вызывается функция WinMain, консоль при этом не создаётся. Соответственно, у вас д.б. функция WinMain с четырьмя параметрами, а не main. Всё. |
|||||
------- Отправлено: 13:08, 02-02-2006 | #4 |
![]() Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать Когда мне нехватает unresolved external XXXX, я ищу файлы *.lib, содержащие текст XXXX и указываю их линкеру. У меня Metrowerks CodeWarrior 8.0. Там достаточно *.lib к проекту добавить.
|
|
Отправлено: 14:29, 02-02-2006 | #5 |
Ветеран Сообщения: 3320
|
Профиль | Отправить PM | Цитировать А как передать программе имя файла который надо проиграть?
Взять к примеру параметры функции main(int argc, char* argv[]). В коде hr = pGraph->RenderFile(L"C:\\Example.avi", NULL) второй параметр должен быть типа const unsigned short * , а в фунции main второй (и т.д) параметр типа char* . Если заменить main(int argc, char* argv[]) на main(int argc, const unsigned short * argv[]) (что естественно нарушает порядок функции main()) программа запустится (только с параметром, без параметров выдаст ошибку), но проигрывать нечего не будет (что и не удивительно ведь main() нарушен). Значит, работать надо со строчкой чтения файла (в самой программе - L"C:\\Example.avi"где L– это приведение типа как я понял). Если кто знает как можно ещё реализировать , то поделитесь кодом плиз. Спасибо за внимание. |
Отправлено: 16:45, 01-07-2006 | #6 |
![]() Ветеран Сообщения: 1180
|
Профиль | Отправить PM | Цитировать На сколько я понял, второй параметр (это должно быть написано в *.h) описан как BSTR* или WSTR*, что по сути - одно и тоже, short*. Скорее вего имеется ввиду уникодовская строка.
//#include <string> // поясняющая вырезка из моей библиотеки std::wstring widen(const std::string& s) { std::wstring w(s.size(), wchar_t()); MultiByteToWideChar(CP_ACP, 0, &s[0], w.size(), &w[0], w.size()); return w; } ... void foo(char* arg) { std::wstring wstr = widen(std::string(arg)); ... hr = pGraph->RenderFile(L"C:\\Example.avi", wstr.c_str()); } |
Отправлено: 18:53, 01-07-2006 | #7 |
Ветеран Сообщения: 3320
|
Профиль | Отправить PM | Цитировать К 1000му просмотру темы, публикую решение. Впрочем, именно сабжевое было найдено ещё тогда – программа линковалась. Просто аппетит возрос и захотелось немного усложнить программу сабжа.
Решение: использовать в коде директивы компилятору #pragma, а в данном конкретном случаи #pragma comment( lib, "strmiids" ) как подсказал ivank. Так же можно подключить через меню, как описано в посте №3 Как найти нужную? Либо искать аналогичные проекты, просматривать документацию или искать по содержимому как рекомендует pva И самое главное, нужно чётко знать какой сейчас проект: консольный, где main рулит, или оконный, где WinMain уже. Тогда не будет проблемы линкования как в посте №3. Регистр имеет значение: пишем main с меленькой буквы. pva я воспользовался функцией MultiByteToWideChar и всё заработало как я того хотел. Выходит параметры приложения воспринимаются кодом как набор байтов, которые она и конвертит в символы. Как её используют нашёл в этом проекте -> http://csclab.murraystate.edu/bob.pi...py/asfcopy.cpp. Вот её описание в MSDN -> http://msdn.microsoft.com/en-us/library/ms776413.aspx Цитата ivank:
Вот собственно код, который линкуется и работает как я хотел. #pragma comment( lib, "strmiids" ) #include <dshow.h> void WaitForCompletion(IGraphBuilder *pGraph) { HRESULT hr; LONG lEvCode = 0; IMediaEvent *pEvent; if (!pGraph) return; hr = pGraph->QueryInterface(IID_IMediaEvent, (void **) &pEvent); if (SUCCEEDED(hr)) { do { MSG Message; while(PeekMessage(&Message, NULL, 0, 0, TRUE)) { TranslateMessage(&Message); DispatchMessage(&Message); } hr = pEvent->WaitForCompletion(10, &lEvCode); } while(lEvCode == 0); pEvent->Release(); } } void main (int argc, char *argv[]) { WCHAR SourceFile[MAX_PATH]; IGraphBuilder *pGraph = NULL; IMediaControl *pControl = NULL; IMediaEvent *pEvent = NULL; // Initialize the COM library. HRESULT hr = CoInitialize(NULL); if (FAILED(hr)) { printf("ERROR - Could not initialize COM library"); return; } // Create the filter graph manager and query for interfaces. hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGraph); if (FAILED(hr)) { printf("ERROR - Could not create the Filter Graph Manager."); return; } hr = pGraph->QueryInterface(IID_IMediaControl, (void **)&pControl); hr = pGraph->QueryInterface(IID_IMediaEvent, (void **)&pEvent); MultiByteToWideChar(CP_ACP, 0, argv[1], -1, SourceFile, NUMELMS(SourceFile)); // Build the graph. IMPORTANT: Change this string to a file on your system. hr = pGraph->RenderFile(SourceFile, NULL); if (SUCCEEDED(hr)) { // Run the graph. hr = pControl->Run(); if (SUCCEEDED(hr)) { WaitForCompletion(pGraph); } } pControl->Release(); pEvent->Release(); pGraph->Release(); CoUninitialize(); } Цитата Admiral:
ivank, pva премного благодарен. |
||
Отправлено: 20:31, 05-05-2008 | #8 |
![]() |
Участник сейчас на форуме |
![]() |
Участник вне форума |
![]() |
Автор темы |
![]() |
Сообщение прикреплено |
| |||||
Название темы | Автор | Информация о форуме | Ответов | Последнее сообщение | |
Август 2009: новая версия DirectX и DirectX SDK | OSZone News | Новости и события Microsoft | 0 | 12-09-2009 00:30 | |
Ошибка - [решено] Проблема с DirectX | Denso | Microsoft Windows 2000/XP | 10 | 01-09-2008 22:56 | |
Службы - [решено] Проблема с DirectX | ktak | Microsoft Windows 2000/XP | 9 | 16-11-2007 13:52 | |
Помогите с линковкой ircd hybrid | Anik | Программное обеспечение Linux и FreeBSD | 0 | 05-05-2007 17:46 |
|