[新闻] dxpcom v0.1 发布

qiezi 2007-04-16
由于windows上一直遇到DLL加载失败的问题,所以测试是在linux上进行的。

dxpcom v0.1下载地址

包括对xpidl的修改,增加了-m d选项,用来产生d接口。-m dwrap选项还在编写中,生成的代码现在还无法使用。

mozilla/xpcom/*.d大部分是用修改过的xpidl生成的,另有一些是使用htod工具转换的。

有空可以帮我测试一下,目前还不保证转换完全正确,但我大致检查了一下应该没什么问题。要注意的是nsISupports.idl转过来以后要把QueryInterface注释掉,改用mozilla.dxpcom.QueryInterface里面的QueryInterface方法,原因是要与extern(Windows)兼容。

build.sh里面配置的是我自己机器上的一些路径,可以根据自己机器的路径进行修改,这个以后看如何解决,把xulrunner运行库都包进来?挺大个的。。

下一版本(0.2)就是完成xpidl的-m dwrap选项,产生异常风格的D接口。

目前代码中没有包含任何授权声明,0.2版本会选一个协议,不知道哪种好一些,BSD?或是mozilla用的这种?最好是限制少一点的。

这里是里面的一个例子:

import mozilla.xpcom.nsXPCOM;
import mozilla.xpcom.nsILocalFile;
import mozilla.xpcom.nsIComponentManager;
import mozilla.xpcom.nsISupports;
import mozilla.dxpcom.StringAPI;
import mozilla.dxpcom.QueryInterface;
import std.string;
import std.stdio;

void main(char[][] args)
{
    nsIComponentManager componentManager;

    nsresult result;
    result = NS_InitXPCOM2(null, null, null);

    result = NS_GetComponentManager(&componentManager);

    nsILocalFile ifile = null;
    result = componentManager.CreateInstanceByContractID(
        "@mozilla.org/file/local;1",
        null,
        &NS_ILOCALFILE_IID,
        cast(void**)&ifile
        );

    writefln("Create nsIFile instance, result: 0x%08x", result);

    AString str = new AString("~/dprojects/dxpcom/test.d"w);
    result = ifile.InitWithPath(cast(nsAString*)str);
    writefln("InitWithPath, result: 0x%08x", result);


    long filesize;
    result = ifile.GetFileSize(&filesize);
    writefln("GetFileSize result: 0x%08x, filesize: %d", result, filesize);

    result = NS_ShutdownXPCOM(null);
    writefln(result);
}

这是没有包含返回值处理的。

下一版的异常风格将是这样的:
void main(char[][] args)
{
    NS_InitXPCOM2D(null, null);

    nsIComponentManagerD componentManager = NS_GetComponentManagerD();

    nsILocalFileD ifile =
        cast(nsILocalFileD)componentManager.CreateInstanceByContractID(
            "@mozilla.org/file/local;1",
            null,
            &NS_ILOCALFILE_IID,
        );

    ifile.InitWithPath("~/dprojects/dxpcom/test.d"w);

    long filesize = ifile.GetFileSize();
    writefln("filesize: %d", filesize);

    NS_ShutdownXPCOMD(null);
}

代码可能会有些小变化,大致是这样的。异常风格的接口会放在mozilla.dxpcom里面。使用时可以选择mozilla.xpcom里面返回值风格的接口,也可以选择moaillz.dxpcom里面异常风格的接口,当然也可以混合使用,如果你觉得这样舒服的话。。。

0.3版本的目标是用D编写XPCOM组件,这个可能要修改DMD或GDC来实现,因为XPCOM虚表与COM虚表有一点点不兼容。
qiezi 2007-04-16
D2.0如果macro功能强大的话,也可以考虑把xpidl现在这个功能做到代码里面去,编译时产生接口。当然这个也要考虑一下编译效率。
h_rain 2007-04-16
强赞!动作真快!呵呵.

前天晚上我都困糊涂了,也没想清楚.
现在看,接口风格两种就够了,一个使用返回值的标准的仿c++的.
再一个,进行了包装的,使用异常的,方便D中使用的.

关于D写xpcom组件,唯一的障碍就是现在的D的接口模型虚表不兼容.
对了,测试过吗?D写接口,C++调用?也不正常吗?
qiezi 2007-04-16
目前这个IDL转换工具是从xpidl_header上修改的,D接口部分还好,比较简单。异常风格包装部分我自己都看糊涂了,方法签名已经可以转换了,还剩下方法实现里面的类型转换、调用转换和返回值转换要做,得花点时间整理一下代码。。。

用D写XPCOM,如果虚表问题解决了,可以直接使用返回值风格的接口来编写。异常风格需要再写一个生成器来做,不过转换方法前面的讨论里面都已经确定了,所以剩下的是工作量的问题。用C写这些还真是麻烦,怎么libIDL没有脚本语言的封装呢。。

XPIDL写得也很一般,容错能力极差,自己写的IDL稍有点问题就转换不过,并且报不出错误,还好并不是经常需要用它。所以如果有时间的话宁愿从头用脚本语言来写一个,或者是D语言,不过就怕支持库太少,这需要一个好用点的IDL解析器。
h_rain 2007-04-16
用D写xpcom组件,只要能提供正确的接口,外面就可以调用了吧?
D里面没必要再弄很复杂的东西了吧?
qiezi 2007-04-16
上面列出了2种D里面调用XPCOM的可能的方式,这里再列一下用D写XPCOM组件的2种方式:

1、返回值风格的,与C++基本一样
class nsLocalFile : nsILocalFile
{
  nsresult QueryInterface(nsIID* iid, void** p)
  {
    // 实现代码
  }

  // 实现返回值风格的XPCOM接口
  nsresult InitWithPath(nsAString* path)
  {

  }
}


2、异常风格的
class nsLocalFileD : nsILocalFileD
{
  nsISupports QueryInterface(nsIID* iid)
  {
    // 实现代码
  }

  // 异常风格的实现,字符串类型使用的是D内值类型
  void InitWithPath(wchar[] path)
  {
  }
}

// 下面部分使用工具生成
class nsLocalFileWrap : nsILocalFile
{
  this(nsILocalFileD inner)
  {
    this.inner = inner;
  }

  nsresult QueryInterface(nsIID* iid, void** p)
  {
    try{
      *p = cast(void*)inner.QueryInterface(iid);
      // 可能还要处理引用计数,防止GC释放掉对象
       // 或者做在AddRef和Release里面,但都是工具自动生成
       return NS_OK;
    }catch(XPCOMException ex){
      return ex.GetErrorCode();
    }
  }

  nsresult InitWithPath(nsAString* path)
  {
    try{
      scope auto _path = new AString(path);
      inner.InitWithPath(_path.GetString());
      return NS_OK;
    }catch(XPCOMException ex){
      return ex.GetErrorCode();
    }
  }
private:
  nsILocalFileD inner;
}
qiezi 2007-04-16
一些C++的东西要换掉的,比如字符串,它用的是nsAString,在D里面再实现一个字符串类多痛苦?必须要转换过来。。
h_rain 2007-04-16
呵呵,我的意思是说,因为是XPCOM组件,对外提供的就是接口,那我们创建D的XPCOM组件的时候,仅仅符合XPCOM的接口规范就可以了,不用再做那么复杂的转换了.
这个对象怎么写都行,只要提供的是标准接口就得了,就是只要有C++返回值风格的接口就够了吧?
h_rain 2007-04-16
因为要转换的这个异常风格的组件是我们自己写的,如果想让工具去自动转换,那又要规定一套规范了.
qiezi 2007-04-16
这是可以选用的。你可以把返回值风格的接口当作是规范,也可以完全无视它,把异常风格的接口当作是规范。目前xpidl生成的java接口就是这么包装过的,不过我还没仔细看。
Global site tag (gtag.js) - Google Analytics