Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » [решено] *DirectX* | DShow и С++, проблема с линковкой программ

Ответить
Настройки темы
[решено] *DirectX* | DShow и С++, проблема с линковкой программ

Ветеран


Сообщения: 3320
Благодарности: 916

Профиль | Отправить PM | Цитировать


Изменения
Автор: Admiral
Дата: 01-02-2006
Кто работать с библиотеками ДиректХ (в особености 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
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


Admiral
Эта ошибка означает, что компилятор не находит реализацию (т.е. непосредственно точку входа в объектном коде) какой-то из использованных функций. Все WinAPI функции, конечно реализованны в соответствующих системных .dll, но компилятор то об этом не знает и даже не умеет напрямую из dll функции импортировать (вернее, раньше не умел, а сейчас с помощью специальных прагм это возможно, вроде. Но нестандартно совсем). Поэтому создаются специальные .lib-заглушки для системных вызовов. Наиболее часто используемые обычно добавляются IDE в проект при его создании автоматически. Я бы поставил на то, что у вас не подключена к проекту ole32.lib, в которой находятся заглушки для CoCreateInstance и иже с ним. Но точно можно будет сказать, если вы приведёте весь текст ошибки, где указывается в том числе и не найденное имя, а по имени уже можно найти и библиотеку соответствующую.

-------
http://ivank.ru

Это сообщение посчитали полезным следующие участники:

Отправлено: 16:08, 01-02-2006 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Ветеран


Сообщения: 3320
Благодарности: 916

Профиль | Отправить PM | Цитировать


ivank
Спасибо за ответ. Теперь стало понятно где искать проблему.

Цитата:
...а сейчас с помощью специальных прагм это возможно, вроде. Но нестандартно совсем
Что это за программы? И действительно ли они столь существенны?
Цитата:
у вас не подключена к проекту ole32.lib
Она подключена по умолчанию. А вот strmiids.lib как раз не мешало (на него я вышел, посмотрев файл с расширением dsp от BGmusic ). После чего всё заработало!

А на счёт
Цитата:
у вас не подключена к проекту .lib ... но точно можно будет сказать, если вы приведёте весь текст ошибки, где указывается в том числе и не найденное имя, а по имени уже можно найти и библиотеку соответствующую.
то как по
Код: Выделить весь код
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 выдайотса аналогичная ошибка
Код: Выделить весь код
LIBCD.lib(wincrt0.obj) : error LNK2001: unresolved external symbol _WinMain@16
?

Р.S
Спасибо за вступительную теорию.
А то я сомневался, что MSVS 6.0 весь битый и ничего путёвого в нём реально не напишиш (напишеш но не получиш ЕХЕ). В Делфи как то проше, но для системных прог С++, как мне кажетса, лутше предназначен.

Последний раз редактировалось Admiral, 02-02-2006 в 03:33.


Отправлено: 22:39, 01-02-2006 | #3


редкий гость


Сообщения: 1696
Благодарности: 44

Профиль | Сайт | Отправить PM | Цитировать


Во-первых, моё предположение всё таки оказалось ложным. Т.к. не найдена была не функция, а экспортируемые переменные. Поскольку гуиды по сути своей шестнадцатибайтные стркутуры, то им надо где-то храниться. Хранят и задают значение _одному_ экземпляру структуры, которй описан/хранится в соответствующем объектном модуле (библиотеке в данном случае), в остальных местах на него тольок _ссылаются_. Поэтому если не слинковать программу с соответствующим файлом, то эти ссылки останутся ни к чему не привязанными, что и произошло. Опять же с помощью расшерений MSVC можно приписать IID/GUID прямо к интерфейсу в месте его описания. Что не есть стандартно.

Цитата:
Цитата:
...а сейчас с помощью специальных прагм это возможно, вроде. Но нестандартно совсем
Что это за программы? И действительно ли они столь существенны?
Не программы, а прагмы. #pragma <и ещё что-то> Это директивы компилятору, с помощью них можно многое сделать, но понимать это будет лишь MSVC, остальные компиляторы имеют свои прагмы. Полные перечень прагм можно найти в MSDN'е.

Цитата:
то как по
Код: Выделить весь код
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
можно определить что нехватает?
Там перечислены имена, которые не удалось найти. Находите их в документации и опеределяете к какой библиотеке они отнсятся, там же будет написано, какие требуется подключить у проекту .lib, что б всё заработало.

Цитата:
А какой оператор можно использовать в коде для подключения библиотек (что б было видно непосредственно, а не так через Project->Settings (ALT+F7))?
Какая-то #pragma, не помнб поскольку MSVC уже давно не пользуюсь.

Цитата:
И почему при добавлении /stack:0x200000,0x200000 /subsystem:windows /machine:I386 /ignore:4089 /ignore:4078 в Project Options выдайотса аналогичная ошибка
Если я правильно помню, то проблема в /subsystem:windows.

В принципе можно выделить два типа приложение - консольные и windows. Первые это /subsystem:console. При этом линкер создаёт точку входа в программу, в которой инициализируются стандартные библиотеки, включая ввод-вывод на консоль (наверное, консоль тоже создаётся заодно) и затем вызывается функция main. Второй тип приложений - windows приложения. /subsystem:windows. При этом линкером создаётся точка входа в программу, в которой то же что-то инициализируется и затем вызывается функция WinMain, консоль при этом не создаётся.

Соответственно, у вас д.б. функция WinMain с четырьмя параметрами, а не main. Всё.

-------
http://ivank.ru

Это сообщение посчитали полезным следующие участники:

Отправлено: 13:08, 02-02-2006 | #4

pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить PM | Цитировать


Когда мне нехватает unresolved external XXXX, я ищу файлы *.lib, содержащие текст XXXX и указываю их линкеру. У меня Metrowerks CodeWarrior 8.0. Там достаточно *.lib к проекту добавить.
Это сообщение посчитали полезным следующие участники:

Отправлено: 14:29, 02-02-2006 | #5


Ветеран


Сообщения: 3320
Благодарности: 916

Профиль | Отправить 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

pva pva вне форума

Аватара для pva

Ветеран


Сообщения: 1180
Благодарности: 279

Профиль | Отправить 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
Благодарности: 916

Профиль | Отправить 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:
Полные перечень прагм можно найти в MSDN'е. »
Он лайн версия -> http://msdn.microsoft.com/en-us/libr...17(VS.60).aspx
Вот собственно код, который линкуется и работает как я хотел.
Код: Выделить весь код
#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(); 
}
Я в него добавил функцию WaitForCompletion, так как в примере от Microsoft не рекомендуется использовать в реальной жизни
Цитата Admiral:
// Note: Do not use INFINITE in a real application, because it
// can block indefinitely. »
Взял её из того же найденного проекта.

ivank, pva премного благодарен.

Отправлено: 20:31, 05-05-2008 | #8



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » [решено] *DirectX* | DShow и С++, проблема с линковкой программ

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Август 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




 
Переход