请教,COM组件获取函数返回值类型(字符串形式的类型名)

TaiJi1985 2021-02-07 07:45:24
现在,我可以根据GetFuncDesc函数获取到 FUNCDESC ,返回值类型是否包含在elemdescFunc ? 查了文档类型是ELEMDESC。

这个字段包含两个字段,我经过动态调试,得知在tdesc中有数据,他是一个TYPEDESC 类型。 这个里面有2个整数。

比如我调试的时候得到:
vt = 26 lpValue=1f835080


如何根据这两个整数得到一个字符串形式的类型名呢? 请教各位大神。 查文档一堆,调试一堆。就是整不出来,拜托了。

或者说上面这个思路是不是有不对的地方? 请大侠指正。

下面附各种文档

==========
TYPEDESC 文档

字段
lpValue
如果变量为 VT_SAFEARRAY 或 VT_PTR,则 lpValue 字段包含指向指定元素类型的 TYPEDESC 的指针。
vt
指示由此 TYPEDESC 描述的项的 Variant 类型。

=======================
ELEMDESC文档
desc
包含有关元素的信息。
tdesc
标识元素的类型。

=================
FUNCDESC 文档

字段
callconv
指定函数的调用约定。
cParams
计算参数的总数。
cParamsOpt
计算可选参数。
cScodes
计算允许的返回值。
elemdescFunc
包含函数的返回类型。
funckind
指定函数是虚拟的、静态的还是仅支持调度的。
invkind
指定属性函数的类型。
lprgelemdescParam
指示 cParams 的大小。
lprgscode
存储函数可在 16 位系统中返回的错误的计数。
memid
标识函数成员 ID。
oVft
指定 FUNC_VIRTUAL 在 VTBL 中的偏移量。
wFuncFlags
指示函数的 FUNCFLAGS。
...全文
423 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
redui 2021-02-23
  • 打赏
  • 举报
回复
何必纠结,枚举名称只是给人看的,IDE能候选,是因为IDL预编译结果(写代码过程中的智能感知需要这个功能,语言服务会即时生成AST供程序员预选、代码lint,类型检查等),目的只是方便程序员阅读,减轻人的记忆负担。运行时给机器看的都是整数,根本没有名称。所以先问自己,你要这个名字何用?
引用 8 楼 TaiJi1985 的回复:
[quote=引用 7 楼 redui 的回复:]几乎所有语言,枚举的默认元类型都是int,只有编译器知道它是枚举,编译器会同时生成枚举常量(像只读的const变量一样使用),用于枚举值比较或匹配。对于使用IDL语言的技术(比如COM),通常也是使用MIDL编译器生成含枚举值定义的源代码,这是编译型的用法。对于解释型动态脚本,比如VBS/JS,它也没办法自动生成枚举定义,你需要使用1、2这类字面值代替枚举项名称。当然,你在C++代码里也可以封装一个方法(比如GetEnumValue("MyEnum", "MyEnumItem"))的方式来返回一个整数值,在这个封装方法里面你可以访问类型库读取所有的枚举项定义。
感谢您的解答。 不过您看,当用C#或者VB访问一个COM组件的时候,写代码时IDE能给出枚举的候选列表,这说明COM中是存在这个候选列表的,我现在想做的就是把它读出来。 知道TypeInfo,是可以得到enum 的枚举项的,枚举项以常量的形式存在。 现在的问题是InvokeMethod返回的直接是一个Int,没办法获取到它的类型。 在FUNCDESC 中也没找到合适的方法。[/quote]
TaiJi1985 2021-02-21
  • 打赏
  • 举报
回复
引用 7 楼 redui 的回复:
几乎所有语言,枚举的默认元类型都是int,只有编译器知道它是枚举,编译器会同时生成枚举常量(像只读的const变量一样使用),用于枚举值比较或匹配。对于使用IDL语言的技术(比如COM),通常也是使用MIDL编译器生成含枚举值定义的源代码,这是编译型的用法。对于解释型动态脚本,比如VBS/JS,它也没办法自动生成枚举定义,你需要使用1、2这类字面值代替枚举项名称。当然,你在C++代码里也可以封装一个方法(比如GetEnumValue("MyEnum", "MyEnumItem"))的方式来返回一个整数值,在这个封装方法里面你可以访问类型库读取所有的枚举项定义。
感谢您的解答。 不过您看,当用C#或者VB访问一个COM组件的时候,写代码时IDE能给出枚举的候选列表,这说明COM中是存在这个候选列表的,我现在想做的就是把它读出来。 知道TypeInfo,是可以得到enum 的枚举项的,枚举项以常量的形式存在。 现在的问题是InvokeMethod返回的直接是一个Int,没办法获取到它的类型。 在FUNCDESC 中也没找到合适的方法。
redui 2021-02-19
  • 打赏
  • 举报
回复
几乎所有语言,枚举的默认元类型都是int,只有编译器知道它是枚举,编译器会同时生成枚举常量(像只读的const变量一样使用),用于枚举值比较或匹配。对于使用IDL语言的技术(比如COM),通常也是使用MIDL编译器生成含枚举值定义的源代码,这是编译型的用法。对于解释型动态脚本,比如VBS/JS,它也没办法自动生成枚举定义,你需要使用1、2这类字面值代替枚举项名称。当然,你在C++代码里也可以封装一个方法(比如GetEnumValue("MyEnum", "MyEnumItem"))的方式来返回一个整数值,在这个封装方法里面你可以访问类型库读取所有的枚举项定义。
TaiJi1985 2021-02-15
  • 打赏
  • 举报
回复
非常感谢您的解答。 这个代码很有用,他解决了知道类型后,如何获取Enum项目的问题:使用COM中的信息重构Enum。 但,我现在卡在 如何获取函数返回值类型这上面。 使用InvokeMethod 的时候,文档中是返回一个Enum的,InvokeMethod全部返回的是一个System.Int32 , 没有类型信息。 如果不是Enum的, InvokeMethod都会带有类型信息System.__COMObject__ ,通过COM的相关函数可以获取确切的类型。 但Int32的不行啊。 不过您给的这个资料非常有价值, 给我开了一扇大门, 这不是例子,这好像是Framework的源码!! 感谢!!!! 我从源码里翻翻看。 如果您对怎么获取函数返回值类型有其他见解,也请不吝赐教。
引用 5 楼 zgl7903 的回复:
微软官网有C#的例子,可以参考下 https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/ComponentModel/COM2Interop/COM2TypeInfoProcessor.cs

    /// <include file='doc\COM2TypeInfoProcessor.uex' path='docs/doc[@for="Com2TypeInfoProcessor.ProcessTypeInfoEnum"]/*' />
        /// <devdoc>
        /// This converts a type info that describes a IDL defined enum
        /// into one we can use
        /// </devdoc>
        private static Type ProcessTypeInfoEnum(UnsafeNativeMethods.ITypeInfo enumTypeInfo, StructCache structCache) {
 
            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum entered");
 
            if (enumTypeInfo == null) {
                Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum got a NULL enumTypeInfo");
                return null;
            }
 
            try {
                IntPtr pTypeAttr = IntPtr.Zero;
                int hr = enumTypeInfo.GetTypeAttr(ref pTypeAttr);
 
                if (!NativeMethods.Succeeded(hr) || pTypeAttr == IntPtr.Zero) {
                        throw new ExternalException(SR.GetString(SR.TYPEINFOPROCESSORGetTypeAttrFailed, hr), hr);
                }
 
                NativeMethods.tagTYPEATTR typeAttr = (NativeMethods.tagTYPEATTR)structCache.GetStruct(typeof(NativeMethods.tagTYPEATTR));//(tagTYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(tagTYPEATTR));
                UnsafeNativeMethods.PtrToStructure(pTypeAttr, typeAttr);
 
                if (pTypeAttr == IntPtr.Zero) {
                    Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: failed to get a typeAttr");
                    return null;
                }
 
                try {
 
                    int nItems = typeAttr.cVars;
 
                    Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: processing " + nItems.ToString(CultureInfo.InvariantCulture) + " variables");
 
                    ArrayList strs = new ArrayList();
                    ArrayList vars = new ArrayList();
 
                    NativeMethods.tagVARDESC varDesc = (NativeMethods.tagVARDESC)structCache.GetStruct(typeof(NativeMethods.tagVARDESC));
                    Object varValue = null;
                    string enumName = null;
                    string name = null;
                    string helpstr = null;
 
                    enumTypeInfo.GetDocumentation(NativeMethods.MEMBERID_NIL, ref enumName, ref helpstr, null, null);
                    
                                                            // For each item in the enum type info,
                    // we just need it's name and value, and helpstring if it's there.
                    //
                    for (int i = 0; i < nItems; i++) {
                        IntPtr pVarDesc = IntPtr.Zero;
                        hr = enumTypeInfo.GetVarDesc(i, ref pVarDesc);
 
                        if (!NativeMethods.Succeeded(hr) || pVarDesc == IntPtr.Zero) {
                            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, String.Format(CultureInfo.CurrentCulture, "ProcessTypeInfoEnum: ignoring item 0x{0:X} because ITypeInfo::GetVarDesc returned hr=0x{1:X} or NULL", hr));
                            continue;
                        }
 
                        try {
                            //varDesc = (tagVARDESC)Marshal.PtrToStructure(pVarDesc, typeof(tagVARDESC));
                            UnsafeNativeMethods.PtrToStructure(pVarDesc, varDesc);
 
                            if (varDesc == null ||
                                varDesc.varkind != (int)NativeMethods.tagVARKIND.VAR_CONST ||
                                varDesc.unionMember == IntPtr.Zero) {
                                continue;
                            }
 
                            name = helpstr = null;
                            varValue = null;
 
                            // get the name and the helpstring
 
                            hr = enumTypeInfo.GetDocumentation(varDesc.memid,  ref name,  ref helpstr, null, null);
 
 
                            if (!NativeMethods.Succeeded(hr)) {
                                Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, String.Format(CultureInfo.CurrentCulture, "ProcessTypeInfoEnum: ignoring item 0x{0:X} because ITypeInfo::GetDocumentation returned hr=0x{1:X} or NULL", hr));
                                continue;
                            }
 
                            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum got name=" + (name == null ? "(null)" : name) + ", helpstring=" + (helpstr == null ? "(null)" : helpstr));
 
                            // get the value
                            try {
                                //varValue = (VARIANT)Marshal.PtrToStructure(varDesc.unionMember, typeof(VARIANT));
                                varValue = Marshal.GetObjectForNativeVariant(varDesc.unionMember);
                            }
                            catch (Exception ex) {
                                Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: PtrtoStructFailed " + ex.GetType().Name + "," + ex.Message);
                            }
 
                            /*if (varValue == null) {
                                Debug.Fail("Couldn't get VARIANT from VARIANTDESC");
                                continue;
                            }*/
 
                            //variant v = varValue.ToVariant();
                            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: adding variable value=" + Convert.ToString(varValue, CultureInfo.InvariantCulture));
                            vars.Add(varValue);
 
                            // if we have a helpstring, use it, otherwise use name
                            string nameString;
                            if (helpstr != null) {
                                nameString = helpstr;
                            }
                            else {
                                Debug.Assert(name != null, "No name for VARDESC member, but GetDocumentation returned S_OK!");
                                nameString = name;
                            }
                            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: adding name value=" + nameString);
                            strs.Add(nameString);
                        }
                        finally {
                            if (pVarDesc != IntPtr.Zero) {
                                enumTypeInfo.ReleaseVarDesc(pVarDesc);
                            }
                        }
                    }
                    structCache.ReleaseStruct(varDesc);
                    Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: returning enum with " + strs.Count.ToString(CultureInfo.InvariantCulture) + " items");
 
                    // just build our enumerator
                    if (strs.Count > 0) {
                        
                        // get the IUnknown value of the ITypeInfo
                        IntPtr pTypeInfoUnk = Marshal.GetIUnknownForObject(enumTypeInfo);
                        
                        try {
                           enumName = pTypeInfoUnk.ToString() + "_" + enumName;
                           
                           if (builtEnums == null) {
                              builtEnums = new Hashtable();
                           }
                           else if (builtEnums.ContainsKey(enumName)) {
                              return (Type)builtEnums[enumName];
                           }
 
                           Type enumType = typeof(int);
 
                           if (vars.Count > 0 && vars[0] != null) {
                               enumType = vars[0].GetType();
                           }
                           
                           EnumBuilder enumBuilder = ModuleBuilder.DefineEnum(enumName, TypeAttributes.Public, enumType);
                           for (int i = 0; i < strs.Count; i++) {
                              enumBuilder.DefineLiteral((string)strs[i], vars[i]);
                           }
                           Type t = enumBuilder.CreateType();
                           builtEnums[enumName] = t;
                           return t;
                        }
                        finally {
                           if (pTypeInfoUnk != IntPtr.Zero) {
                              Marshal.Release(pTypeInfoUnk);
                           }
                        }
                    }
 
                }
                finally {
                    enumTypeInfo.ReleaseTypeAttr(pTypeAttr);
                    structCache.ReleaseStruct(typeAttr);
                }
            }
            catch {
            }
            return null;
        }
 
 
zgl7903 2021-02-13
  • 打赏
  • 举报
回复
微软官网有C#的例子,可以参考下 https://referencesource.microsoft.com/#System.Windows.Forms/winforms/Managed/System/WinForms/ComponentModel/COM2Interop/COM2TypeInfoProcessor.cs

    /// <include file='doc\COM2TypeInfoProcessor.uex' path='docs/doc[@for="Com2TypeInfoProcessor.ProcessTypeInfoEnum"]/*' />
        /// <devdoc>
        /// This converts a type info that describes a IDL defined enum
        /// into one we can use
        /// </devdoc>
        private static Type ProcessTypeInfoEnum(UnsafeNativeMethods.ITypeInfo enumTypeInfo, StructCache structCache) {
 
            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum entered");
 
            if (enumTypeInfo == null) {
                Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum got a NULL enumTypeInfo");
                return null;
            }
 
            try {
                IntPtr pTypeAttr = IntPtr.Zero;
                int hr = enumTypeInfo.GetTypeAttr(ref pTypeAttr);
 
                if (!NativeMethods.Succeeded(hr) || pTypeAttr == IntPtr.Zero) {
                        throw new ExternalException(SR.GetString(SR.TYPEINFOPROCESSORGetTypeAttrFailed, hr), hr);
                }
 
                NativeMethods.tagTYPEATTR typeAttr = (NativeMethods.tagTYPEATTR)structCache.GetStruct(typeof(NativeMethods.tagTYPEATTR));//(tagTYPEATTR)Marshal.PtrToStructure(pTypeAttr, typeof(tagTYPEATTR));
                UnsafeNativeMethods.PtrToStructure(pTypeAttr, typeAttr);
 
                if (pTypeAttr == IntPtr.Zero) {
                    Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: failed to get a typeAttr");
                    return null;
                }
 
                try {
 
                    int nItems = typeAttr.cVars;
 
                    Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: processing " + nItems.ToString(CultureInfo.InvariantCulture) + " variables");
 
                    ArrayList strs = new ArrayList();
                    ArrayList vars = new ArrayList();
 
                    NativeMethods.tagVARDESC varDesc = (NativeMethods.tagVARDESC)structCache.GetStruct(typeof(NativeMethods.tagVARDESC));
                    Object varValue = null;
                    string enumName = null;
                    string name = null;
                    string helpstr = null;
 
                    enumTypeInfo.GetDocumentation(NativeMethods.MEMBERID_NIL, ref enumName, ref helpstr, null, null);
                    
                                                            // For each item in the enum type info,
                    // we just need it's name and value, and helpstring if it's there.
                    //
                    for (int i = 0; i < nItems; i++) {
                        IntPtr pVarDesc = IntPtr.Zero;
                        hr = enumTypeInfo.GetVarDesc(i, ref pVarDesc);
 
                        if (!NativeMethods.Succeeded(hr) || pVarDesc == IntPtr.Zero) {
                            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, String.Format(CultureInfo.CurrentCulture, "ProcessTypeInfoEnum: ignoring item 0x{0:X} because ITypeInfo::GetVarDesc returned hr=0x{1:X} or NULL", hr));
                            continue;
                        }
 
                        try {
                            //varDesc = (tagVARDESC)Marshal.PtrToStructure(pVarDesc, typeof(tagVARDESC));
                            UnsafeNativeMethods.PtrToStructure(pVarDesc, varDesc);
 
                            if (varDesc == null ||
                                varDesc.varkind != (int)NativeMethods.tagVARKIND.VAR_CONST ||
                                varDesc.unionMember == IntPtr.Zero) {
                                continue;
                            }
 
                            name = helpstr = null;
                            varValue = null;
 
                            // get the name and the helpstring
 
                            hr = enumTypeInfo.GetDocumentation(varDesc.memid,  ref name,  ref helpstr, null, null);
 
 
                            if (!NativeMethods.Succeeded(hr)) {
                                Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, String.Format(CultureInfo.CurrentCulture, "ProcessTypeInfoEnum: ignoring item 0x{0:X} because ITypeInfo::GetDocumentation returned hr=0x{1:X} or NULL", hr));
                                continue;
                            }
 
                            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum got name=" + (name == null ? "(null)" : name) + ", helpstring=" + (helpstr == null ? "(null)" : helpstr));
 
                            // get the value
                            try {
                                //varValue = (VARIANT)Marshal.PtrToStructure(varDesc.unionMember, typeof(VARIANT));
                                varValue = Marshal.GetObjectForNativeVariant(varDesc.unionMember);
                            }
                            catch (Exception ex) {
                                Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: PtrtoStructFailed " + ex.GetType().Name + "," + ex.Message);
                            }
 
                            /*if (varValue == null) {
                                Debug.Fail("Couldn't get VARIANT from VARIANTDESC");
                                continue;
                            }*/
 
                            //variant v = varValue.ToVariant();
                            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: adding variable value=" + Convert.ToString(varValue, CultureInfo.InvariantCulture));
                            vars.Add(varValue);
 
                            // if we have a helpstring, use it, otherwise use name
                            string nameString;
                            if (helpstr != null) {
                                nameString = helpstr;
                            }
                            else {
                                Debug.Assert(name != null, "No name for VARDESC member, but GetDocumentation returned S_OK!");
                                nameString = name;
                            }
                            Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: adding name value=" + nameString);
                            strs.Add(nameString);
                        }
                        finally {
                            if (pVarDesc != IntPtr.Zero) {
                                enumTypeInfo.ReleaseVarDesc(pVarDesc);
                            }
                        }
                    }
                    structCache.ReleaseStruct(varDesc);
                    Debug.WriteLineIf(DbgTypeInfoProcessorSwitch.TraceVerbose, "ProcessTypeInfoEnum: returning enum with " + strs.Count.ToString(CultureInfo.InvariantCulture) + " items");
 
                    // just build our enumerator
                    if (strs.Count > 0) {
                        
                        // get the IUnknown value of the ITypeInfo
                        IntPtr pTypeInfoUnk = Marshal.GetIUnknownForObject(enumTypeInfo);
                        
                        try {
                           enumName = pTypeInfoUnk.ToString() + "_" + enumName;
                           
                           if (builtEnums == null) {
                              builtEnums = new Hashtable();
                           }
                           else if (builtEnums.ContainsKey(enumName)) {
                              return (Type)builtEnums[enumName];
                           }
 
                           Type enumType = typeof(int);
 
                           if (vars.Count > 0 && vars[0] != null) {
                               enumType = vars[0].GetType();
                           }
                           
                           EnumBuilder enumBuilder = ModuleBuilder.DefineEnum(enumName, TypeAttributes.Public, enumType);
                           for (int i = 0; i < strs.Count; i++) {
                              enumBuilder.DefineLiteral((string)strs[i], vars[i]);
                           }
                           Type t = enumBuilder.CreateType();
                           builtEnums[enumName] = t;
                           return t;
                        }
                        finally {
                           if (pTypeInfoUnk != IntPtr.Zero) {
                              Marshal.Release(pTypeInfoUnk);
                           }
                        }
                    }
 
                }
                finally {
                    enumTypeInfo.ReleaseTypeAttr(pTypeAttr);
                    structCache.ReleaseStruct(typeAttr);
                }
            }
            catch {
            }
            return null;
        }
 
 
TaiJi1985 2021-02-12
  • 打赏
  • 举报
回复
折腾几天,问题仍未解决,请哪位大神来指导一下。 获取设置属性都没问题, 调用方法也没问题,枚举方法也没问题。 但是对于一些enum类型的属性,获取到的值是int值,也没有类型信息,没法转成Enum中的枚举项。
TaiJi1985 2021-02-08
  • 打赏
  • 举报
回复
补充一点我查到的资料。 vt 的类型解释 VARIANT类型变量的vt值,得以确认: enum VARENUM { VT_EMPTY =0, VT_NULL = 1, VT_I2 = 2, VT_I4 = 3, VT_R4 = 4, VT_R8 = 5, VT_CY = 6, VT_DATE = 7, VT_BSTR = 8, VT_DISPATCH = 9, VT_ERROR = 10, VT_BOOL = 11, VT_VARIANT = 12, VT_UNKNOWN = 13, VT_DECIMAL = 14, VT_I1 = 16, VT_UI1 = 17, VT_UI2 = 18, VT_UI4 = 19, VT_I8 = 20, VT_UI8 = 21, VT_INT = 22, VT_UINT = 23, VT_VOID = 24, VT_HRESULT = 25, VT_PTR = 26, VT_SAFEARRAY = 27, VT_CARRAY = 28, VT_USERDEFINED = 29, VT_LPSTR = 30, VT_LPWSTR = 31, VT_RECORD = 36, VT_FILEtiME = 64, VT_BLOB = 65, VT_STREAM = 66, VT_STORAGE = 67, VT_STREAMED_OBJECT = 68, VT_STORED_OBJECT = 69, VT_BLOB_OBJECT = 70, VT_CF = 71, VT_CLSID = 72, VT_BSTR_BLOB = 0xfff, VT_VECTOR = 0x1000, VT_ARRAY = 0x2000, VT_BYREF = 0x4000, VT_RESERVED = 0x8000, VT_ILLEGAL = 0xffff, VT_ILLEGALMASKED = 0xfff, VT_TYPEMASK = 0xfff };
TaiJi1985 2021-02-08
  • 打赏
  • 举报
回复
引用 1 楼 zgl7903的回复:
Enumerate COM object (IDispatch) methods using ATL?
谢谢,我仔细阅读了您给的这个文档。 我对于枚举所有方法是没有问题的,对于调用方法也没有问题,只是获取函数返回值类型存在问题。 我现在实际想做做的是,有的函数返回值是一个enum,但调用函数后得到的是一个整数如13,我想把这个13自动转换成枚举字符串。 这就需要在调用函数前先了解返回值类型,才能根据类型获取enum相关信息。然后进行查表转换。

3,245

社区成员

发帖
与我相关
我的任务
社区描述
ATL,Active Template Library活动(动态)模板库,是一种微软程序库,支持利用C++语言编写ASP代码以及其它ActiveX程序。
社区管理员
  • ATL/ActiveX/COM社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧