Com-interop:为什么tlibimp.exe生成只读属性

Com interop: Why tlibimp.exe generates read only properties?

本文关键字:只读属性 exe tlibimp 为什么 Com-interop      更新时间:2023-10-16

我已经用Visual Studio创建了一个COM对象,我想将它与Delphi一起使用。

[Guid("9D0CCD2D-75E9-46AC-BC40-C4D84669FC45")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IMyComClassDispatch
{
    string PropertyString { get; set; }
    string funcGetString();
    void funcSetString(string aString);
}
[ClassInterface(ClassInterfaceType.None)]
public class MyComClassDispatch : IMyComClassDispatch
{
    public string PropertyString { get; set; }

    public string varString;
    public string funcGetString()
    {
        return varString;
    }
    public void funcSetString(string aString)
    {
        varString = aString;
    }
}

然后我生成了tlb文件,最后生成了一个与我的COM对象相对应的pascal文件,该文件与Delphi5:捆绑在一起

C:>tlibimp.exe -P+ mylib.tlb

这是生成的代码:

// *********************************************************************//
// DispIntf:  IMyComClassDispatch
// Flags:     (4096) Dispatchable
// GUID:      {9D0CCD2D-75E9-46AC-BC40-C4D84669FC45}
// *********************************************************************//
  IMyComClassDispatch = dispinterface
    ['{9D0CCD2D-75E9-46AC-BC40-C4D84669FC45}']
    property PropertyString: WideString readonly dispid 1610743808;
    function  funcGetString: WideString; dispid 1610743810;
    procedure funcSetString(const aString: WideString); dispid 1610743811;
  end;

问题是我的属性被标记为只读,我真的不明白为什么会发生这种情况,因为这个工具也可以生成C++代码,并且可以修改属性:

// *********************************************************************//
// Interface   : IMyComClassDispatch
// Indicateurs : (4096) Dispatchable
// GUID        : {9D0CCD2D-75E9-46AC-BC40-C4D84669FC45}
// *********************************************************************//
interface IMyComClassDispatch : public TDispWrapper<IDispatch>
{
  BSTR __fastcall get_PropertyString()
  {
    _TDispID _dispid(/* PropertyString */ DISPID(DISPID_UNKNOWN/*[1610743808]*/));
    TAutoArgs<0> _args;
    OlePropertyGet(_dispid, _args);
    return _args.GetRetVariant();
  }
  void __fastcall set_PropertyString(BSTR Param1/*[in]*/)
  {
    _TDispID _dispid(/* PropertyString */ DISPID(1610743808));
    TAutoArgs<1> _args;
    _args[1] = Param1 /*[VT_BSTR:0]*/;
    OlePropertyPut(_dispid, _args);
  }
  BSTR __fastcall funcGetString()
  {
    _TDispID _dispid(/* funcGetString */ DISPID(DISPID_UNKNOWN/*[1610743810]*/));
    TAutoArgs<0> _args;
    OleFunction(_dispid, _args);
    return _args.GetRetVariant();
  }
  void __fastcall funcSetString(BSTR aString/*[in]*/)
  {
    _TDispID _dispid(/* funcSetString */ DISPID(DISPID_UNKNOWN/*[1610743811]*/));
    TAutoArgs<1> _args;
    _args[1] = aString /*[VT_BSTR:0]*/;
    OleProcedure(_dispid, _args);
  }

  __property   BSTR            PropertyString = {read = get_PropertyString, write = set_PropertyString};
};

这是否意味着我应该避免使用COM对象的属性,或者是否有任何选项我应该更改?这是tlibmp的问题,还是编译器无法生成在COM对象属性上写入的指令的限制?

如有任何帮助,我们将不胜感激!

这是Delphi5&6 tlibimp.exe。您应该升级到Delphi 7或更高版本以避免它。

Tlibimp.exe在Delphi 5中被窃听,Borland/CodeGear/Enbarcadero不再支持。。。

解决方法是删除生成的pas文件上的只读标记。但为了确保代码被正确调用,我做了一些修改来证明它是有效的:

  • 在COM对象类中,在setter中写入一个文件:

    public string PropertyString
    {
        get { return varString; }
        set
        {
            varString = value;
            File.WriteAllText(@"C:UserseliasDocumentscom.txt", varString);
        }
    }
    
  • 删除从tlibimp.exe:生成的.pas文件中属性的只读标记

    // *********************************************************************//
    // DispIntf:  IMyComClassDispatch
    // Flags:     (4096) Dispatchable
    // GUID:      {9D0CCD2D-75E9-46AC-BC40-C4D84669FC45}
    // *********************************************************************//
      IMyComClassDispatch = dispinterface
        ['{9D0CCD2D-75E9-46AC-BC40-C4D84669FC45}']
        property PropertyString: WideString dispid 1610743808;
        function  funcGetString: WideString; dispid 1610743810;
        procedure funcSetString(const chaine: WideString); dispid 1610743811;
      end;
    
  • 然后你可以使用你的COM对象:

    var
      MyClass: IMyComClassDispatch;
    begin
      try
        MyClass:= CoMyComClassDispatch.Create;
        MyClass.PropertyString:= 'some value';
      finally
        MyClass._Release;
      end;
    end;
    

文件写入正确!

现在这是我在项目中遇到的唯一问题,我希望以后不会有任何其他问题。。。