error LNK2001: 无法解析的外部符号 "public: virtual long __stdcall CBaseFilter(转)

时间:2022-05-17 10:42:53

原文转自 https://www.cnblogs.com/xiongjiaji/archive/2010/12/31/2476565.html

今天用VS2005编译DirectShow程序,发现出来很多莫名其妙的链接错误:如下:
 
error LNK2001: 无法解析的外部符号 "public: virtual long __stdcall CBaseFilter::FindPin(wchar_t const *,struct IPin * *)" (?FindPin@CBaseFilter@@UAGJPB_WPAPAUIPin@@@Z)
error LNK2001: 无法解析的外部符号 "public: virtual long __stdcall CBaseFilter::JoinFilterGraph(struct IFilterGraph *,wchar_t const *)" (?JoinFilterGraph@CBaseFilter@@UAGJPAUIFilterGraph@@PB_W@Z)
error LNK2001: 无法解析的外部符号 "public: virtual long __stdcall CBaseFilter::QueryVendorInfo(wchar_t * *)" (?QueryVendorInfo@CBaseFilter@@UAGJPAPA_W@Z)

上网一查,发现如下设置即可:
C/C++ | Language | Treat wchar_t as built-in type: yes?no?
默认为是,设置为否即可

在我的项目中正好相反,默认是 否,有上面的问题,改成是则编译成功。

(1) 为什么会出现这种错误呢?是因为VC6以及VS2003在wchar_t内置的选项上默认为No,而VS2005在此选项上默认为Yes,我今天使用VS2005打开原来VS2003建立的BaseClass项目,使得选项为No,这样编译出来的基类库的选项就是No了。
    然后,在使用VS2005新建DirectShow程序时,默认选项为Yes,这样程序与基类的选项就不一致了,在函数的参数涉及到wchar_t时,程序的链接会由于生成的名字不同而导致链接不上(同样是wchar_t,链接时lib文件的符号是不同的)。
    弄清楚这个问题之后,此选项的选择就无所谓了,只要工程和Lib在该选项上一致即可

(2) 通过查看定义CBasefilter类的头文件(amfilter.h)我发现其中关于构造函数的定义有如下代码 
C/C++ code public: CBaseFilter( const TCHAR *pName, // Object description LPUNKNOWN pUnk, // IUnknown of delegating object CCritSec *pLock, // Object who maintains lock REFCLSID clsid); // The clsid to be used to serialize this filter CBaseFilter( TCHAR *pName, // Object description LPUNKNOWN pUnk, // IUnknown of delegating object CCritSec *pLock, // Object who maintains lock REFCLSID clsid, // The clsid to be used to serialize this filter HRESULT *phr); // General OLE return code #ifdef UNICODE CBaseFilter( const CHAR *pName, // Object description LPUNKNOWN pUnk, // IUnknown of delegating object CCritSec *pLock, // Object who maintains lock REFCLSID clsid); // The clsid to be used to serialize this filter CBaseFilter( CHAR *pName, // Object description LPUNKNOWN pUnk, // IUnknown of delegating object CCritSec *pLock, // Object who maintains lock REFCLSID clsid, // The clsid to be used to serialize this filter HRESULT *phr); // General OLE return code #endif 
所以我想,vs默认编码就是unicode的,所以应该用的构造函数时下面两个,于是我把调用CBasefilter构造函数的地方改成 
C/C++ code CBaseFilter("NetSender", lpunk, &mFilterLock, CLSID_NetSender) 
原来是 
C/C++ code CBaseFilter(NAME("NetSender"), lpunk, &mFilterLock, CLSID_NetSender) 
其他的构造函数的调用也进行相应的改造,果然将这些link error都给kill掉了^_^ 
但是还有一处有问题就是关于CPosPassThru这个构造函数,这个类的构造函数没有定义unicode版本的,只有这样一个构造函数 
C/C++ code CPosPassThru(const TCHAR *, LPUNKNOWN, HRESULT*, IPin *); 
我去掉NAME宏以后出现如下错误 
C/C++ code error C2664: 'CPosPassThru::CPosPassThru(const TCHAR *,LPUNKNOWN,HRESULT *,IPin *)' : cannot convert parameter 1 from 'const char [13]' to 'const TCHAR *' 
我使用NAME宏的话,又出现连接错误 
C/C++ code error LNK2028: unresolved token (0A00024D) "public: __thiscall CPosPassThru::CPosPassThru(unsigned short const *,struct IUnknown *,long *,struct IPin *)" (??0CPosPassThru@@$$FQAE@PBGPAUIUnknown@@PAJPAUIPin@@@Z) 
也就是说,它认为我给它传入的第一个参数是一个unsigned short const char*类型 
1,请问为什么我使用NAME宏,它会认为我使用的是unsigned short const char*类型,NAME宏不就是TEXT宏么,而TEXT宏不就是可以将常量字符创转换成TCHAR*么? 
2,如何解决这个问题,我想也就是如何将unsigned short const char*转换成TCHAR*的问题。