`
qiezi
  • 浏览: 491108 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

COM接口IDL转换为D接口以及__uuidof实现。

    博客分类:
  • D
阅读更多
D语言里面,可以通过version(Windows)来兼容COM接口,不过对于__uuidof却没有相应实现。

原始COM接口定义类似这样(找个简单的):

[
    local,
    
object,
    uuid(594f31d0
-7f19-11d0-b194-00a0c90dc8bf)
]
interface IRpcChannelBuffer2 : IRpcChannelBuffer
{

    HRESULT GetProtocolVersion
    (
        [
in,out] DWORD *pdwVersion
    );
}

VC++中可通过__uuidof操作符来获取COM接口中的uuid“元”信息。

转换为D接口后代码如下:

version(Windows) {

interface IRpcChannelBuffer2 : IRpcChannelBuffer
{
    HRESULT GetProtocolVersion (DWORD
* pdwVersion);
}

}

失去了uuid信息。只要稍作修改,在转换时保存uuid,即可以模板来模拟实现__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);
}

如上面代码,接口在转换时,把:

[
    local,
    
object,
    uuid(594f31d0
-7f19-11d0-b194-00a0c90dc8bf)
]
interface IRpcChannelBuffer2 : IRpcChannelBuffer
{

    HRESULT GetProtocolVersion
    (
        [in,out] DWORD *pdwVersion
    );
}


转换为:

template __uuidof(T:IRpcChannelBuffer2)
{
    IID __uuidof 
= IIDFromStr!("594f31d0-7f19-11d0-b194-00a0c90dc8bf");
}
version (Windows) {

interface IRpcChannelBuffer2 : IRpcChannelBuffer {
    HRESULT GetProtocolVersion (DWORD
* pdwVersion);
}

}

即可,这个可以交由自动化工具完成。

由于__uuidof模板值在编译期决议,没有实际的运行期开销。
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics