D語言里面,可以通過version(Windows)來兼容COM接口,不過對于__uuidof卻沒有相應(yīng)實現(xiàn)。
原始COM接口定義類似這樣(找個簡單的):
[
????local,
????object,
????uuid(594f31d0-7f19-11d0-b194-00a0c90dc8bf)
]
interface?IRpcChannelBuffer2?:?IRpcChannelBuffer
{
????HRESULT?GetProtocolVersion
????(
????????[in,out]?DWORD?*pdwVersion
????);
}
VC++中可通過__uuidof操作符來獲取COM接口中的uuid“元”信息。
轉(zhuǎn)換為D接口后代碼如下:
version(Windows)?{
interface?IRpcChannelBuffer2?:?IRpcChannelBuffer
{
????HRESULT?GetProtocolVersion?(DWORD*?pdwVersion);
}
}
失去了uuid信息。只要稍作修改,在轉(zhuǎn)換時保存uuid,即可以模板來模擬實現(xiàn)__uuidof操作符。
import?std.c.windows.com;
import?std.string;
import?std.stdio;
private:
template?HexStrToUbyte(char[]?str)
{
????const?ubyte?HexStrToUbyte?=?cast(ubyte)HexStrToUlong!(str);
}
template?HexStrToUshort(char[]?str)
{
????const?ushort?HexStrToUshort?=?cast(ushort)HexStrToUlong!(str);
}
template?HexStrToUint(char[]?str)
{
????const?uint?HexStrToUint?=?cast(uint)HexStrToUlong!(str);
}
template?HexStrToUlong(char[]?str)
{
????static?if?(str.length?==?1)
????????const?ulong?HexStrToUlong?=?HexToUbyte!(str[0..1]);
????else
????????const?ulong?HexStrToUlong?
????????????=?HexToUbyte!(str[length-1..length])?
??????????????+?16UL?*?HexStrToUlong!(str[0..length-1]);
}
private:
template?HexToUbyte(char[]?c)
{
????static?if?(c[0]?>=?'0'?&&?c[0]?<=?'9')
????????const?ubyte?HexToUbyte?=?c[0]?-?'0';
????else?static?if?(c[0]?==?'A'?||?c[0]?==?'a')
????????const?ubyte?HexToUbyte?=?0xa;
????else?static?if?(c[0]?==?'B'?||?c[0]?==?'b')
????????const?ubyte?HexToUbyte?=?0xb;
????else?static?if?(c[0]?==?'C'?||?c[0]?==?'c')
????????const?ubyte?HexToUbyte?=?0xc;
????else?static?if?(c[0]?==?'D'?||?c[0]?==?'d')
????????const?ubyte?HexToUbyte?=?0xd;
????else?static?if?(c[0]?==?'E'?||?c[0]?==?'e')
????????const?ubyte?HexToUbyte?=?0xe;
????else?static?if?(c[0]?==?'F'?||?c[0]?==?'f')
????????const?ubyte?HexToUbyte?=?0xf;
}
template?HexToUbyte_bug(char?c)
{
????static?if?(c?>=?'0'?&&?c?<=?'9')
????????const?ubyte?HexToUbyte1?=?c?-?'0';
????else?static?if?(c?==?'A'?||?c?==?'a')
????????const?ubyte?HexToUbyte1?=?0xa;
????else?static?if?(c?==?'B'?||?c?==?'b')
????????const?ubyte?HexToUbyte1?=?0xb;
????else?static?if?(c?==?'C'?||?c?==?'c')
????????const?ubyte?HexToUbyte1?=?0xc;
????else?static?if?(c?==?'D'?||?c?==?'d')
????????const?ubyte?HexToUbyte1?=?0xd;
????else?static?if?(c?==?'E'?||?c?==?'e')
????????const?ubyte?HexToUbyte1?=?0xe;
????else?static?if?(c?==?'F'?||?c?==?'f')
????????const?ubyte?HexToUbyte1?=?0xf;
}
template?IIDFromStr(char[]?str)
{
????const?IID?IIDFromStr?=?{
????????HexStrToUint!(str[0..8]),
????????HexStrToUshort!(str[9..13]),?
????????HexStrToUshort!(str[14..18]),
????????[
??????????HexStrToUbyte!(str[19..21]),
??????????HexStrToUbyte!(str[21..23]),?
??????????HexStrToUbyte!(str[24..26]),
??????????HexStrToUbyte!(str[26..28]),?
??????????HexStrToUbyte!(str[28..30]),
??????????HexStrToUbyte!(str[30..32]),?
??????????HexStrToUbyte!(str[32..34]),
??????????HexStrToUbyte!(str[34..36])
????????]
????};
}
template?__uuidof(T:IUnknown)
{
????IID?__uuidof?=?IIDFromStr!("00000000-0000-0000-C000-000000000046");
}
template?__uuidof(T:IClassFactory)
{
????IID?__uuidof?=?IIDFromStr!("00000001-0000-0000-C000-000000000046");
}
void?main()
{
????IID?iu??=?__uuidof!(IUnknown);
????IID?icp?=?__uuidof!(IClassFactory);
????writefln(iu.Data1);
????writefln(iu.Data2);
????writefln(iu.Data3);
????writefln(iu.Data4);
}
如上面代碼,接口在轉(zhuǎn)換時,把:
[
????local,
????object,
????uuid(594f31d0-7f19-11d0-b194-00a0c90dc8bf)
]
interface IRpcChannelBuffer2 : IRpcChannelBuffer
{
??? HRESULT GetProtocolVersion
??? (
??????? [in,out] DWORD *pdwVersion
??? );
}
轉(zhuǎn)換為:
template?__uuidof(T:IRpcChannelBuffer2)
{
????IID?__uuidof?=?IIDFromStr!("594f31d0-7f19-11d0-b194-00a0c90dc8bf");
}
version?(Windows)?{
interface?IRpcChannelBuffer2?:?IRpcChannelBuffer?{
????HRESULT?GetProtocolVersion?(DWORD*?pdwVersion);
}
}
即可,這個可以交由自動化工具完成。
由于__uuidof模板值在編譯期決議,沒有實際的運行期開銷。