[疑难] xpcom.dll为何不能正常加载?
qiezi
2007-04-12
要解决这个问题也是可以的,不直接调用接口的QueryInterface,而是调用一个通用的QueryInterfaceX,在它里面调用接口的QueryInterface,完成之后把虚表指针减少一个指针大小就可以了。
就是有点麻烦。 GUID是难看点,不过以后IPv6了,IP地址也一样难看。资源多了嘛就得用这么长的东西来管理。 |
|
oldrev
2007-04-12
还有个 std.windows.unknown.d
|
|
qiezi
2007-04-12
oldrev 写道 还有个 std.windows.unknown.d
没看到哪里用这个,而且它是个class,不知道做什么的。 |
|
oldrev
2007-04-12
在D里用COM好像很麻烦,唯一只有 juno 项目提供了一个 tlbimpd 的程序为导入库生成D声明,偶尔还会产生错误。
tlbimpd 产生的类还依赖 juno.com,虽然可以手工修改,可是毕竟很麻烦,尤其是像 mshtml.tlb 这样3万多行的文件 |
|
qiezi
2007-04-12
不是D里面用COM麻烦,是导入库太少。。可以自己只写一些自己要用到的,还是比较方便的,比起其它语言来说。
|
|
h_rain
2007-04-12
class NS_NO_VTABLE nsISupports { public: NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) = 0; NS_IMETHOD_(nsrefcnt) AddRef(void) = 0; NS_IMETHOD_(nsrefcnt) Release(void) = 0; }; #define NS_DEFINE_STATIC_IID_ACCESSOR(the_iid) \ static const nsIID& GetIID() {static const nsIID iid = the_iid; return iid;} class NS_NO_VTABLE nsIComponentManager : public nsISupports { public: NS_DEFINE_STATIC_IID_ACCESSOR(NS_ICOMPONENTMANAGER_IID) NS_IMETHOD GetClassObject(const nsCID & aClass, const nsIID & aIID, void * *result) = 0; NS_IMETHOD GetClassObjectByContractID(const char *aContractID, const nsIID & aIID, void * *result) = 0; NS_IMETHOD CreateInstance(const nsCID & aClass, nsISupports *aDelegate, const nsIID & aIID, void * *result) = 0; NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aDelegate, const nsIID & aIID, void * *result) = 0; }; nsIComponentManager* cm; nsresult rv; rv = NS_GetComponentManager(&cm); 这东西乱呼呼的一片! 我在Mozilla中找到的代码片段 |
|
qiezi
2007-04-12
nsIComponentManager里的方法我还没用到,没有影响,它排在虚表后面。现在的问题是COM对象虚表第1个元素不知道是什么,第2个才是COM对象的第1个方法QueryInterface,extern(Windows)声明的接口和它是对应的,而XPCOM对象虚表第1个就是QueryInterface方法,extern(Windows)把它跳过了。想到了解决办法,就是不美观,晚点测试一下。
|
|
oldrev
2007-04-12
搞不懂了,既然叫“跨平台COM” 怎么还用 Windows 的调用约定,按道理应该是 extern(C) 啊
|
|
qiezi
2007-04-12
是调用约定。extern(C)是cdecl,extern(Windows)其实是__stdcall,不是说Windows专有的。
区别是extern(C)声明的函数由调用者清理堆栈,extern(Windows)由函数自己清理堆栈。另外接口中的方法也是extern(Windows)的,this作为参数压入堆栈,否则this指针是从寄存器传入。 |
|
h_rain
2007-04-12
typedef struct IM0 { int QueryInterface; int AddRef; int Release; int GetClassObject; int GetClassObjectByContractID; int CreateInstance; int CreateInstanceByContractID; }IM0; typedef struct IM1 { struct IM0 *p; }IM1; nsIComponentManager* cm; nsresult rv; rv = NS_GetComponentManager(&cm); printf("0x%08x=QueryInterface\r\n",cm->QueryInterface); printf("0x%08x=AddRef\r\n",cm->AddRef); printf("0x%08x=Release\r\n",cm->Release); printf("0x%08x=GetClassObject\r\n",cm->GetClassObject); printf("0x%08x=GetClassObjectByContractID\r\n",cm->GetClassObjectByContractID); printf("0x%08x=CreateInstance\r\n",cm->CreateInstance); printf("0x%08x=CreateInstanceByContractID\r\n\r\n",cm->CreateInstanceByContractID); IM1 *m=(IM1*)cm; printf("0x%08x=QueryInterface\r\n",m->p->QueryInterface); printf("0x%08x=AddRef\r\n",m->p->AddRef); printf("0x%08x=Release\r\n",m->p->Release); printf("0x%08x=GetClassObject\r\n",m->p->GetClassObject); printf("0x%08x=GetClassObjectByContractID\r\n",m->p->GetClassObjectByContractID); printf("0x%08x=CreateInstance\r\n",m->p->CreateInstance); printf("0x%08x=CreateInstanceByContractID\r\n\r\n",m->p->CreateInstanceByContractID); rv = NS_GetComponentManager((nsIComponentManager**)&m); printf("0x%08x=QueryInterface\r\n",m->p->QueryInterface); printf("0x%08x=AddRef\r\n",m->p->AddRef); printf("0x%08x=Release\r\n",m->p->Release); printf("0x%08x=GetClassObject\r\n",m->p->GetClassObject); printf("0x%08x=GetClassObjectByContractID\r\n",m->p->GetClassObjectByContractID); printf("0x%08x=CreateInstance\r\n",m->p->CreateInstance); printf("0x%08x=CreateInstanceByContractID\r\n\r\n",m->p->CreateInstanceByContractID); 输出 0x0042ecde=QueryInterface 0x0042ee4b=AddRef 0x0042f00d=Release 0x0042ecb1=GetClassObject 0x0042dd16=GetClassObjectByContractID 0x0042de33=CreateInstance 0x0042ddf7=CreateInstanceByContractID 0x10065b50=QueryInterface 0x10065a00=AddRef 0x10065a70=Release 0x10067bf0=GetClassObject 0x10067d30=GetClassObjectByContractID 0x10068250=CreateInstance 0x10068380=CreateInstanceByContractID 0x10065b50=QueryInterface 0x10065a00=AddRef 0x10065a70=Release 0x10067bf0=GetClassObject 0x10067d30=GetClassObjectByContractID 0x10068250=CreateInstance 0x10068380=CreateInstanceByContractID 为什么cm->QueryInterface与m->p->QueryInterface的值不一样? 是不是因为这是成员函数指针啊?直接这么显示与调用的时候的真实取址不一样? |