當我按如下方式運行代碼時,我不斷收到一組錯誤:
LNK 2001 unresolved external symbol IID_IMediaEvent
LNK 2001 unresolved external symbol IID_IMediaControl
LNK 2001 unresolved external symbol IID_IGraphBuilder
LNK 2001 unresolved external symbol CLSID_FilterGraph
我的代碼在這里:
#include <dshow.h>
#include <stdio.h>
#include <Windows.h>
void main(void)
{
HRESULT hr = CoInitialize(NULL);
if (FAILED(hr))
{
printf("FAIL");
}
else
{
printf("PASS");
}
IGraphBuilder *pGraph=NULL;
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;
}
IMediaControl *pControl=NULL;
IMediaEvent *pEvent=NULL;
hr = pGraph->lpVtbl->QueryInterface(pGraph,&IID_IMediaControl, (void**)&pControl);
hr = pGraph->lpVtbl->QueryInterface(pGraph,&IID_IMediaEvent, (void**)&pEvent);
hr = pGraph->lpVtbl->RenderFile(pGraph,L"C:/Users/User/Desktop/AudioPlayer/trn.wav", NULL);
hr = pControl->lpVtbl->Run(pControl);
long evCode = 0;
pEvent->lpVtbl->WaitForCompletion(pEvent,INFINITE, &evCode);
pControl->lpVtbl->Release(pControl);
pEvent->lpVtbl->Release(pEvent);
pGraph->lpVtbl->Release(pGraph);
CoUninitialize();
}
我一直在尋找大約兩個星期試圖找到答案,但沒有任何幫助。我認為它與聯結器有關,但我不知道我做錯了什么,因為我對 C 和 Visual Studio 還很陌生。
uj5u.com熱心網友回復:
這里的核心問題是介面 ( IID) 和類 ( CLSID) ID 已宣告,但未定義。編譯器愉快地繼續,將 ID 查找委托給聯結器。由于任何提供的匯入庫都沒有定義或匯出 ID,因此聯結器放棄了LNK2001錯誤。
要解決此問題,有兩種選擇:或者讓頭檔案也定義 ID,或者將strmiids.lib匯出它們的匯入庫 ( ) 傳遞給聯結器。
第一個選項的優點是可以使用任何編譯器。它需要一個#include <initguid.h>指令,然后才能包含任何僅宣告 ID 的頭檔案。<initguid.h>做了兩件事:它定義了INITGUID前處理器符號,隨后包含<guiddef.h>. 后者更改前處理器符號以定義相應的 ID,并正確標記__declspec(selectany)以防止多重定義的符號聯結器錯誤。
#include <initguid.h>
#include <dshow.h>
#include <stdio.h>
#include <Windows.h>
...
這應該可以解決所有聯結器錯誤。
另一種選擇是將匯入庫傳遞strmiids.lib給聯結器。這可以使用#pragma comment(lib, "strmiids")指令在源代碼中完成,或者通過在聯結器命令列上傳遞匯入庫來完成。
這樣做的缺點是它需要特定于工具鏈:只有 MSVC 和 Clang 支持#pragma comment(lib, ...),而 Clang 和 GCC 對匯入庫使用不同的命名(libfoovs. foo.lib)。除非您有特定的理由使用匯入庫,否則您應該使用第一個選項。
旁白:既然#include <initguid.h>適用于任何場景,為什么我們有選擇?為什么我們需要<initguid.h>切換?
__declspec(selectany)從引入修飾符之前的時間(Visual Studio 2012)開始,這可能歸因于歷史事件。在此之前,每個符號最多只能定義一次。如果多個編譯單元定義了相同的符號,則聯結器將生成LNK2005,并最終無法生成工件。
在那些時候,客戶端代碼通常會有一個(通常是空的)編譯單元,它有一個#include <initguid.h>指令,然后是其他宣告(和定義)ID 的頭檔案。其余的編譯單元僅包含用于宣告 ID 的頭檔案,沒有<initguid.h>切換。
引入修飾符后__declspec(selectany),符號(例如 ID)可以定義任意多次,只要定義相同(SDK 確保這一點)。所以今天,你可以簡單地#include <initguid.h>在每個編譯單元中作業,一切都很好。
至少這是我<guiddef.h>通過查看Windows SDK 檔案得出的歷史解釋。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/528650.html
標籤:C温纳皮直播
上一篇:帶有過濾器的自定義產品回圈(自定義產品欄位)WooCommerce
下一篇:檢查和保護C 中的執行緒
