小编Jas*_*out的帖子

如何自动初始化Delphi记录?

要初始化Delphi记录,我总是添加一个初始化为已知良好默认值的方法(类或对象).Delphi还允许使用参数定义记录"构造函数",但是您无法定义自己的无参数"构造函数".

TSomeRecord = record
 Value1: double;
 Value2: double;

 procedure Init;
end;

procedure TSomeRecord.Init;
begin
  Value1 := MaxDouble;
  Value2 := Pi;
end; 
Run Code Online (Sandbox Code Playgroud)

鉴于上述记录,没有警告说记录尚未初始化.开发人员可能会忽略调用Init记录.有没有办法自动将记录初始化为我的默认值,可能不仅仅是一个简单的FillChar;

例如

var 
  LSomeRecord: TSomeRecord
begin
  // someone forgot to call LSomeRecord.Init here
  FunctionThatTakesDefaultSomeRecord(LSomeRecord);
end; 
Run Code Online (Sandbox Code Playgroud)

如何将记录自动初始化为我的默认值?

[注意]我不想在答案后修改问题.任何读者都可以阅读关于使用类方法进行初始化而不是变异对象方法的最佳实践的注释.

delphi

10
推荐指数
2
解决办法
5278
查看次数

当实现在多个库中时,Delphi [弱]引用属性会产生"无效类类型转换"

德尔福柏林10.1增加了[弱]参考.Marco Cantu的博客有一些基础知识.

对于我的测试,我创建了两个包含两个自动化对象类型的COM库.容器对象包含内容对象的列表,而内容对象包含对其容器的弱引用.

以下两个方案已经过测试并正常工作(弱引用设置为null并释放内存):

  • 具有接口和CoClasses的单个COM库.
  • 两个COM库,一个带有接口,另一个带有CoClasses

但是,当我将coclasses放在两个单独的库中时,代码会生成"无效类类型转换",删除[weak]属性时错误消失.请原谅奇数样本,其目的只是为了使问题最小化,不应该作为标准编码实践

这是第一个库.ridl文件,它定义了接口和容器的CoClass:

[
  uuid(E1EE3651-A400-49BF-B5C5-006D9943B9C0),
  version(1.0)

]
library DelphiIntfComLib
{

  importlib("stdole2.tlb");

  interface IMyContainer;
  interface IMyContent;
  coclass MyContainer;


  [
    uuid(A7EF86F7-40CD-41EE-9DA1-4D9B7B24F06B),
    helpstring("Dispatch interface for MyContainer Object"),
    dual,
    oleautomation
  ]
  interface IMyContainer: IDispatch
  {
    [id(0x000000C9)]
    HRESULT _stdcall Add([in] IMyContent* AMyContent);
  };

  [
    uuid(BFD6D976-8CEF-4264-B95A-B5DA7817F6B3),
    helpstring("Dispatch interface for MyContent Object"),
    dual,
    oleautomation
  ]
  interface IMyContent: IDispatch
  {
    [id(0x000000C9)]
    HRESULT _stdcall SetWeakReferenceToContainer([in] IMyContainer* AContainer);
  };

  [
    uuid(1F56198B-B1BE-4E11-BC78-0E6FF8E55214)
  ]
  coclass MyContainer
  {
    [default] interface IMyContainer;
  };

};
Run Code Online (Sandbox Code Playgroud)

这是我的容器实现

unit Unit1; …
Run Code Online (Sandbox Code Playgroud)

delphi com delphi-10.1-berlin

9
推荐指数
2
解决办法
1065
查看次数

异步TADOQuery的OnFetchComplete未与主线程同步

当使用TADOQuerywith [eoAsyncFetchNonBlocking]和附加到OnFetchComplete事件时,我发现它OnFetchComplete没有在主线程中执行(在XE4和XE8中测试).我认为这是一个错误*,因为我们大多数人都会在这些类型的事件中在UI中工作.我认为这是大型项目中一些问题的根源,我需要一个解决方法.

[编辑]*在阅读ADO文档后,我知道承认这可能不是一个错误,但多线程问题仍然存在.

是否有一种优雅的方法来强制在此处理程序中使用代码在主线程上执行?我不想使用计时器(但如果这是我将采取的唯一解决方案).或者,是否存在ADO同步对象,我可以在此等待或向ADO提供商发送其他形式的信令?

这是一个简化的示例,显示了问题.我的项目更复杂,工厂创建和填充这些数据集,但这里类似于将数据集附加到网格内部ADOQuery1FetchComplete.

unit Unit4;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Data.DB, Data.Win.ADODB, Vcl.StdCtrls;

type
  TForm4 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    ADOQuery1: TADOQuery;
    ADOConnection1: TADOConnection;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure ADOQuery1FetchComplete(DataSet: TCustomADODataSet;
      const Error: Error; var EventStatus: TEventStatus);
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
    FMainThreadID : DWORD;
  public
    { Public declarations }
  end;

var
  Form4: TForm4;

implementation

{$R *.dfm} …
Run Code Online (Sandbox Code Playgroud)

delphi asynchronous tadoquery delphi-xe4 delphi-xe8

7
推荐指数
1
解决办法
1348
查看次数

我可以从缓冲区(pByte)和大小创建VarArray OleVariant而无需复制吗?

我可以将内存从缓冲区复制到安全数组中,如下所示

  function GetVarArrayFromBuffer(ABuffer : pByte; ASizeInBytes: Cardinal) : OleVariant;
  var
    LVarArrayPtr: Pointer;     
  begin
    Result := VarArrayCreate([0, ASizeInBytes - 1], varByte);
    LVarArrayPtr := VarArrayLock(Result);
    try
      Move(ABuffer^, LVarArrayPtr^, ASizeInBytes);
    finally
      VarArrayUnLock(Result);
    end;
  end;
Run Code Online (Sandbox Code Playgroud)

但是,有没有办法直接将我的指针和大小传递到一个varArray类型OleVariant而不复制内存?

[编辑]

我可以看到里面的数组OleVariant是a SAFEARRAY(定义为PVarArray = ^TVarArray),所以看起来应该有一种方法可以通过填充a中的值TVarArray并设置VType和中的VArray值来实现OleVariant.

delphi safearray delphi-xe4

5
推荐指数
1
解决办法
741
查看次数

如何在Delphi中使用RTTI或TypeInfo获取枚举的有效范围

我在测试项目中使用RTTI来评估枚举值,最常见的是对象的属性.如果枚举超出范围,我想显示类似于评估/修改IDE窗口所显示的文本.像"(超出范围)255"之类的东西.

下面的示例代码使用TypeInfo将枚举之外的值显示为使用时的访问冲突GetEnumName.使用RTTI或TypeInfo的任何解决方案都会对我有帮助,我只是不知道我的测试代码中的枚举类型

program Project60;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils,  TypInfo;

Type
  TestEnum = (TestEnumA, TestEnumB, TestEnumC);

const
  TestEnumUndefined = TestEnum(-1);

  procedure WriteEnum(const ATypeInfo: PTypeInfo; const AOrdinal: Integer);
  begin
    WriteLn(Format('Ordinal: %d = "%s"', [AOrdinal, GetEnumName(ATypeInfo, AOrdinal)]));
  end;


var
  TestEnumTypeInfo: PTypeInfo;
begin

  try
    TestEnumTypeInfo := TypeInfo(TestEnum);

    WriteEnum(TestEnumTypeInfo, Ord(TestEnumA));
    WriteEnum(TestEnumTypeInfo, Ord(TestEnumB));
    WriteEnum(TestEnumTypeInfo, Ord(TestEnumC));
    WriteEnum(TestEnumTypeInfo,  Ord(TestEnumUndefined));   //AV

  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
  ReadLn;
end.
Run Code Online (Sandbox Code Playgroud)

delphi rtti delphi-10.2-tokyo

4
推荐指数
1
解决办法
210
查看次数

如果落在浮点类型的无损范围内,两个整数的乘积是否会无损?

单精度双精度IEEE 754 Base 2 浮点值可以无损失地表示整数范围。

给定的产物A = BC,其中,BC是整数表示无损作为浮点值,是产品A总是无损如果它在数学上的浮点类型的无损范围内?

更具体地说,我们是否知道常见的现代处理器是否会确保计算乘积,以便整数乘积的行为如上所述?

编辑:为了澄清上面的链接,可以无损表示的整数范围在双精度中为 +-2 53,在单精度中为 +-16777216。

编辑:IEEE-754 要求将运算四舍五入到最接近的可表示精度,但我特别想知道现代处理器的行为

floating-point precision processor floating-accuracy

3
推荐指数
1
解决办法
119
查看次数