import com; import win.guid; import raw.interface; namespace com; class interface{ ctor(implObject,declInterface){ //允许省略 implObject 参数且不占用参数位置 if(declInterface===null) declInterface,implObject = implObject,{}; elseif(implObject===null) implObject = {}; //检查接口类有效性,并将类的静态成员 IID 转换为 win.guid 结构体 declInterface = checkInterface(declInterface,2); //实现 COM 原生接口 if( (!implObject@) && type(implObject) == "table" ){ var implTable = ..table.mix(implObject, { //实现 IUnknown 接口 QueryInterface = function(iid,ptr){ iid = ..raw.convert(iid, ..win.guid() ); if( iid == IUnknown.IID ){ this.AddRef() return 0/*_S_OK*/,this ; } if( iid == declInterface.IID){ this.AddRef() return 0x0/*_S_OK*/,this; } return -2147467262/*_E_NOINTERFACE*/ }; AddRef = function(){ this.count = ( this.count : 0 ) + 1; __gcRefImplTable__[this] = true; return this.count; }; Release = function(){ this.count = ( this.count : 0 ) - 1; if( this.count < 1 ) { __gcRefImplTable__[this] = null}; return this.count; } } ); this = ..raw.interface( implTable, declInterface ); this[["_(AARDIO/COM.INTERFACE/RAW/IID)_"]] = declInterface.IID; } //导入 COM 原生接口 else{ var pItface = ..com.GetIUnknown(implObject,declInterface.IID); assert(pItface,"无效的 COM 指针"); this = ..raw.interface( pItface, declInterface ); var queryInterface = this.QueryInterface; this.QueryInterface = function(declInterface){ declInterface = checkInterface(declInterface,2); var hr,implObject = queryInterface( declInterface.IID ); if( (hr)>=0/*_SUCCEEDED*/ ){ var obj = ..com.interface(implObject,declInterface); ..com.Release(implObject); return obj; } else { return null,..lasterr(hr); } } } } } namespace interface{ ::Ole32 := ..raw.loadDll("ole32.dll"); CoCreateInstance := ::Ole32.api("CoCreateInstance","int(struct rclsid, pointer pUnkOuter,INT dwClsContext, struct riid, pointer &ppv)" ) var guid = ..win.guid; checkInterface = function(interface,el=1){ var interfaceType = type(interface); if(interfaceType!=type.class){ if( interfaceType == type.string && ! ..com.interface[interface] ) error("无效的接口类",el+1); interface = ..com.interface[interface]; if( type(interface) != type.class ) error("无效的接口类",el+1); } interface.IID = guid.valid(interface.IID) if( ! interface.IID ) error("未指定有效的接口 IID (类的静态成员,字符串或 win.guid 对象)",el+1); return interface; } checkError = function(hr,ci = 1){ if( hr<0/*_FAILED*/ ) error(..lasterr(hr),ci + 1) } create = function(clsid,declInterface,context=7/*_CLSCTX_INPROC | _CLSCTX_LOCAL_SERVER*/){ if(declInterface === null){ declInterface = clsid; clsid = null; } if(clsid===null){ declInterface = clsid; return ..com.interface(declInterface); } if(type(clsid)==type.string) clsid = guid.fromString(clsid) declInterface = checkInterface(declInterface,2); var iid =declInterface.IID ; var hr,unknown =CoCreateInstance(clsid,null,context,iid ); checkError(hr,2); var iterface = ..com.interface(unknown,declInterface); ..com.Release(unknown) return iterface; } var tlbTemplate = /* namespace com.interface; class ${INTERFACE}{ ctor(){ this = ..com.interface.IUnknown(); if(self._funtions){ ..table.assign(this,_funtions); } }; ${FIELD} } ${INTERFACE}.IID = "${IID}" */ loadTypelibrary = function(tlb,interface){ if(type(tlb) === type.string){ tlb = ..com.LoadTypeLibrary(tlb); } if(!tlb){ error("请指定正确的类型库",2) } for(i=1;tlb.GetTypeInfoCount();1){ var info = tlb.GetTypeInfo(i) if(info.GetDocumentation().name===interface){ var attr = info.GetTypeAttr(); if(attr.typekind === "interface"){ var fields = {} for(i=1;attr.Funcs;1){ var f = info.GetFuncDesc(i) ..table.push(fields,"ptr " + (f.name:"unknown")); } var code = ..string.replace(tlbTemplate,"@${FIELD}",..string.join(fields,";")); var code = ..string.replace(code,"@${IID}",attr.GUID); var code = ..string.replace(code,"@${INTERFACE}",interface); loadcodex(code); } } } } class IUnknown{ ptr QueryInterface = "int(struct iid,ptr &ptr)" ; ptr AddRef = "int()" ; ptr Release ="int()" ; } IUnknown.IID = guid.fromString("{00000000-0000-0000-C000-000000000046}"); __gcRefImplTable__ = {}; } /**intellisense(com.interface) checkInterface(__/*接口声明类*/) = 参数可指定 COM 原生接口声明类,\n或者用字符串指定 com.interface 命名空间已导入的声明类名称。\n\n此函数检查接口声明类是否有效,\n如果有效则返回声明接口的类对象,并将类的静态 IID 成员转换为 win.guid 结构体。\n如果是无效的声明类则抛出异常,可使用参数 @2 指定抛出异常的调用级别。 checkError(__/*请输入原生函数返回值*/) = 如果有错误调用 error 函数抛出异常\n可选用参数 @2 指定抛出异常的调用级别:\n调用级别为 2 表示调用当前函数的函数 loadTypelibrary(.(类型库,接口类名) = 自类型库加载接口类,\n并在 com.interface 命名空间创建参数 @2 指定名称的接口声明类,\n类型库可以是路径等 com.LoadTypeLibrary 函数可支持的参数,\n也可以是该函数创建的类型库对象。\n可选在定义接口类以后,\n在该类的命名空间下使用 _funtions 对象补全函数原型 IUnknown = COM 原生接口声明类的基类。\n所有 COM 原生接口声明类必须直接继承此接口。\n所有 COM 原生接口声明类中的自定义函数必须用 owner 代替 this,\nowner 才指向实际绑定的 COM 原生对象。\nCOM 原生接口声明类内部的 this 指向的是声明类而不是 COM 对象。 create( = 创建或实现原生接口 create(.(clsid,declInterface) = 创建原生接口对象,参数 @1 指定 CLSID。\n参数 declInterface 必须指定 com.interface 命名空间下的接口声明类,\n或者用字符串指定 com.interface 命名空间已导入的声明类名称。 create(.(declInterface) = 实现原生接口。\n与直接调用 com.interface(declInterface) 作用相同。\n可以在对象返回后再增加 COM 接口声明类 declInterface 声明的接口方法。 create() = !comInterface. end intellisense**/ /**intellisense() com.interface = 所有 COM 原生接口声明类都在此命名空间内。\n所有 COM 原生接口声明类中的自定义函数必须用 owner 代替 this,\n\nowner 才指向实际绑定的 COM 原生对象。\nCOM 原生接口声明类内部的 this 指向的是声明类而不是 COM 对象。 com.interface( = 导入或实现 COM 原生接口对象。 com.interface(.(implObjectOrPtr,declInterface) = 导入 COM 原生接口对象。\n参数 implObjectOrPtr 可指定 COM 对象、COM 对象指针、com.IUnknown 托管指针。\n参数 declInterface 必须指定 com.interface 命名空间下的接口声明类,\n或者用字符串指定 com.interface 命名空间已导入的声明类名称。\n在 COM 接口类中的自定义函数必须用 owner 代替 this 访问当前 COM 对象。 com.interface(.(implTable,declInterface) = 实现 COM 原生接口对象。\nimplTable 是一个纯表(元表), 并定义与接口匹配的成员函数(被调用时忽略未定义成员)。\n参数 declInterface 必须指定 com.interface 命名空间下的接口声明类,\n或者用字符串指定 com.interface 命名空间已导入的声明类名称。\n在 COM 接口类中的自定义函数必须用 owner 代替 this 访问当前 COM 对象。 com.interface(.(declInterface) = COM 原生接口对象。\n参数 declInterface 必须指定 com.interface 命名空间下的接口声明类,\n或者用字符串指定 com.interface 命名空间已导入的声明类名称。。\n可以对返回对象添加匹配 declInterface 声明的成员函数。\n未定义成员在被调用时忽略并直接返回 0 com.interface() = !comInterface. end intellisense**/ /*****intellisense(!comInterface) AddRef() = 引用计数加一,返回引用计数。\n返回值仅具有测试意义。 Release() = 引用计数减一,返回引用计数。\n返回值仅具有测试意义。 QueryInterface(__/*接口数*/) = 参数是接口类,参考com.interface.IUnknown源码 QueryInterface() = !comInterface. end intellisense*****/ /**intellisense() _SUCCEEDED = @ __/*hr*/ >= 0/*_SUCCEEDED*/ _FAILED = @ __/*hr*/ < 0/*_FAILED*/ _CLSCTX_INPROC_SERVER=@1/*_CLSCTX_INPROC_SERVER*/ _CLSCTX_INPROC_HANDLER=@2/*_CLSCTX_INPROC_HANDLER*/ _CLSCTX_LOCAL_SERVER=@4/*_CLSCTX_LOCAL_SERVER*/ _CLSCTX_SERVER=@5/*_CLSCTX_LOCAL_SERVER*/ _CLSCTX_INPROC=@3/*_CLSCTX_INPROC*/ _VT_EMPTY=@0/*_VT_EMPTY*/ _VT_NULL=@1/*_VT_NULL*/ _VT_I2=@2/*_VT_I2*/ _VT_I4=@3/*_VT_I4*/ _VT_R4=@4/*_VT_R4*/ _VT_R8=@5/*_VT_R8*/ _VT_CY=@6/*_VT_CY*/ _VT_DATE=@7/*_VT_DATE*/ _VT_BSTR=@8/*_VT_BSTR*/ _VT_DISPATCH=@9/*_VT_DISPATCH*/ _VT_ERROR=@0xA/*_VT_ERROR*/ _VT_BOOL=@0xB/*_VT_BOOL*/ _VT_VARIANT=@0xC/*_VT_VARIANT*/ _VT_UNKNOWN=@0xD/*_VT_UNKNOWN*/ _VT_DECIMAL=@0xE/*_VT_DECIMAL*/ _VT_I1=@0x10/*_VT_I1*/ _VT_UI1=@0x11/*_VT_UI1*/ _VT_UI2=@0x12/*_VT_UI2*/ _VT_UI4=@0x13/*_VT_UI4*/ _VT_I8=@0x14/*_VT_I8*/ _VT_UI8=@0x15/*_VT_UI8*/ _VT_INT=@0x16/*_VT_INT*/ _VT_UINT=@0x17/*_VT_UINT*/ _VT_VOID=@0x18/*_VT_VOID*/ _VT_HRESULT=@0x19/*_VT_HRESULT*/ _VT_PTR=@0x1A/*_VT_PTR*/ _VT_SAFEARRAY=@0x1B/*_VT_SAFEARRAY*/ _VT_CARRAY=@0x1C/*_VT_CARRAY*/ _VT_USERDEFINED=@0x1D/*_VT_USERDEFINED*/ _VT_LPSTR=@0x1E/*_VT_LPSTR*/ _VT_LPWSTR=@0x1F/*_VT_LPWSTR*/ _VT_RECORD=@0x24/*_VT_RECORD*/ _VT_INT_PTR=@0x25/*_VT_INT_PTR*/ _VT_UINT_PTR=@0x26/*_VT_UINT_PTR*/ _VT_FILETIME=@0x40/*_VT_FILETIME*/ _VT_BLOB=@0x41/*_VT_BLOB*/ _VT_STREAM=@0x42/*_VT_STREAM*/ _VT_STORAGE=@0x43/*_VT_STORAGE*/ _VT_STREAMED_OBJECT=@0x44/*_VT_STREAMED_OBJECT*/ _VT_STORED_OBJECT=@0x45/*_VT_STORED_OBJECT*/ _VT_BLOB_OBJECT=@0x46/*_VT_BLOB_OBJECT*/ _VT_CF=@0x47/*_VT_CF*/ _VT_CLSID=@0x48/*_VT_CLSID*/ _VT_VERSIONED_STREAM=@0x49/*_VT_VERSIONED_STREAM*/ _VT_BSTR_BLOB=@0xFFF/*_VT_BSTR_BLOB*/ _VT_VECTOR=@0x1000/*_VT_VECTOR*/ _VT_ARRAY=@0x2000/*_VT_ARRAY*/ _VT_BYREF=@0x4000/*_VT_BYREF*/ _VT_RESERVED=@0x8000/*_VT_RESERVED*/ _VT_ILLEGAL=@0xFFFF/*_VT_ILLEGAL*/ _VT_ILLEGALMASKED=@0xFFF/*_VT_ILLEGALMASKED*/ _VT_TYPEMASK=@0xFFF/*_VT_TYPEMASK*/ end intellisense**/