==================================================================
MFC的DLL/EXE中无法使用属性化COM/ATL,原因在于属性化要求有module属性,否则编译不过,而如果有module属性的话,这个属性在编译时会自动生成DllMain/WinMain,与MFC中已有的会冲突。好的解决方案目前没有想到,只想到可能的一个,就是打开工程的Fx属性(C/C++ >> Output Files >> Expand Attributed Source),再修性module属性生成的代码。
==================================================================
带有[out]属性的形参,如果是接口则必须是双指针类型,如果是基本类型,则可以是单指针类型;
BSTR整体可以看作基本类型,所以BSTR*可以带上[out]。
纯粹的[in]属性意味着,服务端只使用实参内容;如果形参是Interface指针,则可以利用接口方法间接调用client;如果是一般指针,则server只能使用指针内容而无法向client输出信息.
纯粹的[out]属性意味着,服务端不使用实参内容而只向实参输出信息, 且形参一定是指针(基本类型)或者双指针(接口类型);
纯粹的[int,out]属性意味着, 服务端使用实参内容的同时还向实参输出信息, 且形参一定是指针(基本类型)或者双指针(接口类型);
==================================================================
接口中不能使用bool, 不能使用非基本类型如CAtlString、CComBSTR,(但是可以由基本类型组成的纯结构体?),必须返回HRESULT;
如果要用到LPVOID形参,则方法要加上[local]属性:[local] HRESULT Method(LPVOID pVoid);
============================================
来自MSDN:
1, _ATL_ATTRIBUTES 工程中,使用IDL文件的方法是使用属性[importidl(idl_file)];
2, 非_ATL_ATTRIBUTES工程中使用[属性]的方法是使用向导。
============================================
link设置项 /ignoreidl=false时,如果调用了其它“静态库”导出的C_Style API,且该API中有使用interface为参数的话,则在生成的idl文件中会产生redefnition冲突:一是来是interface.h的定义;二是来自编译那个“静态库”时,interface.h产生的定义。两个interface.h其实是同一个文件,但是存放在在不同电脑中不同路径里的。原因是由于静态库包含了所有代码信息,属性化DLL中只要调用了静态库中任何一个函数,MIDL便会处理整个静态库工程中所有出现过的接口属性。使用动态库则没有问题,所以静态库中最好不要包含属性化接口(最好不开启静态库工程的_ATL_ATTRIBUTES属性),否则其无法在属性化并且/ignoreidl=false的ATL工程中使用。
问题模拟重现:
一、建立一个_ATL_ATTRIBUTES工程,并用向导添加一个atl 类,去掉生成的头文件中的类,只保留接口备用;
二、建立一个static lib工程,并在c/c++预处理宏中加上_ATL_ATTRIBUTES, 在stdafx.h中加上atlbase.h和atlcom.h;然后再添加函数,函数形参使用第一步的接口指针;
三、建立一个ATL DLL的属性化工程,并调用第二步的函数, 这一步在link时, MIDL便会报错 redefinition, 查看工程目录下以下划线开头的idl文件,可知问题所在。
注:函数体可以不写,只留花括号模拟问题即可。
猜想解决方案:
1,[no_injected_text(true)]。先打开C/C++开关 /Fx,再修改生成的源码,并把修改后的整体paste到工程中对应的file中,然后重新编译,这次因为有no_injected_text属性,不会再生成属性代码。(不行,南辕北辙了)
方案2, 在上面第三步中,将相关头文件位置放在与第二步相同位置(已经证实可行)。
方案3,在相关cpp文件中,插入idl属性[emitidl(false/restrict)];这样可以阻止该cpp文件中的idl属性产生idl代码到最后生成的idl文件中,但是阻止不了引入的静态库产生idl代码。(证实可行,相反属性[importidl(idl_file)];强制引入idl)
============================================
选择了/ignoreidl=false后,要rebuild整个工程,否则会register失败,因为typelib资源没有嵌入到resource中。
{
typedef BOOL (WINAPI *_ChangeWindowMessageFilter)( UINT , DWORD);
BOOL bResult = FALSE;
_ChangeWindowMessageFilter pChangeWindowMessageFilter =
(_ChangeWindowMessageFilter) GetProcAddress( GetModuleHandle(L"user32.dll"), "ChangeWindowMessageFilter" );
if (!pChangeWindowMessageFilter)
{
return FALSE;
}
return pChangeWindowMessageFilter( uMessageID, bAllow ? 1 : 2 );//MSGFLT_ADD: 1, MSGFLT_REMOVE: 2
}