转载请标明是引用于 http://blog.csdn.net/chenyujing1234
平台:VS2005+MIPSSDK
例子代码:
http://www.rayfile.com/zh-cn/files/7020e9b8-7240-11e1-b9ea-0015c55db73d/
参考书本:
《EVC高级编程及其应用开发》
1、新建MFC DLL工程。
创建时,选择 自动,这样就会自动产生
DllCanUnloadNow PRIVATE
DllGetClassObject PRIVATE
DllRegisterServer PRIVATE
DllUnregisterServer PRIVATE
2、添加组件和接口定义.
//声明组件GUID {50AF86CD-AAF2-43B8-8802-483CFF78EF38} //DEFINE_GUID(CLSID_TimeLogServer, //0x50AF86CD,0xAAF2,0x43B8,{0x88,0x02,0x48,0x3C,0xFF,0x78,0xEF,0x38}; static const IID CLSID_TimeLogServer = {0x50AF86CD,0xAAF2,0x43B8,{0x88,0x02,0x48,0x3C,0xFF,0x78,0xEF,0x38}}; // 声明接口GUID{E6A499D6-E5D2-42CE-8DBA-2BA217DC0470} //DEFINE_GUID(IID_ITimeLog, //0xE6A499D6,0xE5D2,0x42CE,{0x8D,0xBA,0x2B,0xA2,0x17,0xDC,0x04,0x70}; static const IID IID_ITimeLog = {0xE6A499D6,0xE5D2,0x42CE,{0x8D,0xBA,0x2B,0xA2,0x17,0xDC,0x04,0x70}}; //接口ITimeLog的声明 DECLARE_INTERFACE_(ITimeLog,IUnknown) { STDMETHOD(OutputLog)(BSTR* varLogText)PURE; };
以下有两个作用:一是定义组件和接口的GUID值(可通过guidgen.exe来产生。
二是使用DECLARE_INTERFACE_宏来声明接口。
该宏的第一个参数为接口名,第二个参数为该接口的基类.注:如果该接口没有基类,那么应该用宏DECLARE_INTERFACE
#define STDMETHOD(method) virtual HRESULT STDMETHODCALLTYPE method
表方法OutputLog返回值为HRESULT.PURE,该解释为="0",也就是纯虚函数,当方法返回值不是HRESULT时,应该使用宏STDMETHOD_(返回值,函数名)
3、声明组件类CTimeLogSeriver并实现接口的嵌套类。
右击工程->添加类,新建类CTimeLogServer,基类为CCmdTarget,在生成的TimeLogServer.h中
添加以下宏
DECLARE_DYNCREATE(CTimeLogserver) //声明实现ITimelog接口的嵌套类 BEGIN_INTERFACE_PART(TimeLog,ITimeLog)//自动声明IUnknown接口的三个方法 STDMETHOD(OutputLog)(BSTR* varLogText); END_INTERFACE_PART(TimeLog) //声明接口映射 DECLARE_INTERFACE_MAP() //声明类厂 DECLARE_OLECREATE(CTimeLogserver)
protected: // Generated message map functions //{{AFX_MSG(CTimeLogServer) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG
DECLARE_MESSAGE_MAP()
在类里做了三件事:
DECLARE_DYNCREATE(CTimeLogserver)->声明实现ITimelog接口的嵌套类->声明接口映射->声明类厂->消自映射
此时编译报以下错
1>正在链接... 1> 正在创建库 DbAu13xx (MIPSII)\Debug/MFC_com.lib 和对象 DbAu13xx (MIPSII)\Debug/MFC_com.exp 1>TimeLogserver.obj : error LNK2001: 无法解析的外部符号 "protected: virtual struct AFX_INTERFACEMAP const * __cdecl CTimeLogserver::GetInterfaceMap(void)const " (?GetInterfaceMap@CTimeLogserver@@MBAPBUAFX_INTERFACEMAP@@XZ) 1>TimeLogserver.obj : error LNK2001: 无法解析的外部符号 "public: virtual long __cdecl CTimeLogserver::XTimeLog::QueryInterface(struct _GUID const &,void * *)" (?QueryInterface@XTimeLog@CTimeLogserver@@UAAJABU_GUID@@PAPAX@Z) 1>TimeLogserver.obj : error LNK2001: 无法解析的外部符号 "public: virtual unsigned long __cdecl CTimeLogserver::XTimeLog::AddRef(void)" (?AddRef@XTimeLog@CTimeLogserver@@UAAKXZ) 1>TimeLogserver.obj : error LNK2001: 无法解析的外部符号 "public: virtual unsigned long __cdecl CTimeLogserver::XTimeLog::Release(void)" (?Release@XTimeLog@CTimeLogserver@@UAAKXZ) 1>TimeLogserver.obj : error LNK2001: 无法解析的外部符号 "public: virtual long __cdecl CTimeLogserver::XTimeLog::OutputLog(wchar_t * *)" (?OutputLog@XTimeLog@CTimeLogserver@@UAAJPAPA_W@Z)
先不管,这是因为纯虚函数没有实现的原因
4、实现类厂和接口映射
IMPLEMENT_DYNCREATE(CTimeLogserver, CCmdTarget)
//实现类厂
IMPLEMENT_OLECREATE(CTimeLogserver,"TimeLogserver",
0x50AF86CD,0xAAF2,0x43B8,0x88,0x02,0x48,0x3C,0xFF,0x78,0xEF,0x38);
//映射接口到相应的嵌套类,把TimeLog映射到CTimeLogserver
BEGIN_INTERFACE_MAP(CTimeLogserver,CCmdTarget)
INTERFACE_PART(CTimeLogserver,IID_ITimeLog,TimeLog)
END_INTERFACE_MAP()
5、实现XTimeLog类的IUnknow接口。
//为XTimeLog嵌套类实现IUnknown接口
//实现IUnknown接口的AddRef方法
STDMETHODIMP_(ULONG)
CTimeLogserver::XTimeLog::AddRef()
{
METHOD_PROLOGUE(CTimeLogserver,TimeLog)
return pThis->ExternalAddRef();
}
//实现IUnknown接口的Release()方法
STDMETHODIMP_(ULONG)
CTimeLogserver::XTimeLog::Release()
{
METHOD_PROLOGUE(CTimeLogserver,TimeLog)
return pThis->ExternalRelease();
}
//实现IUnknown接口的QueryInterface方法
STDMETHODIMP
CTimeLogserver::XTimeLog::QueryInterface(REFIID riid,void**ppvObj)
{
METHOD_PROLOGUE(CTimeLogserver,TimeLog)
return pThis->ExternalQueryInterface(&riid,ppvObj);
}
IUnknown接口有三个最基本的方法AddRef Release QueryInterface.
虽然CCmdTartget类已经实现了IUnknow接口,但必须将嵌套类的IUnknown映射到CCmdTarget支持的IUnknow接口中。
METHOD_PROLOGUE宏的两个参数用于指定实现组件对象的类和实现接口的嵌套类
6、实现ITimeLog接口的OutputLog方法
CTimeLogserver::XTimeLog::OutputLog(BSTR* varLogText) { METHOD_PROLOGUE(CTimeLogserver,TimeLog) if(pThis->m_logfile) { CTime TimeStamp = CTime::GetCurrentTime(); CString NowTime; NowTime.Format(_T("%d年%d月%d日%d:%d %d"),TimeStamp.GetYear(),TimeStamp.GetMonth(),TimeStamp.GetDay(), TimeStamp.GetHour(),TimeStamp.GetMinute(),TimeStamp.GetSecond()); CString LogText((LPCWSTR)*varLogText); fwprintf(pThis->m_logfile,L"\n%s\n%s\n%",NowTime,LogText); return NOERROR; } else { AfxMessageBox(L"没有日志文件!"); return S_FALSE; } }
7、在CMFC_ComApp类初始应用程序和退出应用程序方法里添加"增加全局引用计数"和"减少全局引用计数"
================================
最后在布署时会提示
1>------ 已启动部署: 项目: MFC_com, 配置: Debug DbAu13xx (MIPSII) ------
1>c:\documents and settings\administrator\桌面\mfc_com_server\dbau13xx (mipsii)\debug\MFC_com.dll
1>正在注册文件...
1>部署和/或注册失败,错误为: 0x8973190e。 写入文件“\Storage Card\MFC_com.dll”时出错。错误 0x8007007e: 找不到指定的模块。
1>
========== 生成: 0 已成功, 0 已失败, 1 最新, 0 已跳过 ==========
========== 部署: 0 已成功, 1 已失败, 0 已跳过 ==========
解决方法:
工程->常规->MFC的使用 改为 在静态中使用MFC