小编Ste*_*nke的帖子

如何在Delphi中将TComparer <T>类传递给泛型?

我想创建具有某些功能(包括搜索功能)的通用记录。为了执行此搜索,我想传递一个自定义的比较器来比较项目。如果它是一个类,我可以在构造函数中传递它,但是我想使用一条记录来避免创建或释放它。因此,我没有在哪里初始化比较器的构造函数。

然后,我决定像类型参数一样传递Comparer类,并在需要比较器时,使用TComparer.Default创建比较器的实例。

好吧,这是代码:

TMyArray<T,C: TComparer<T>> = record
  FComparer: IComparer<T>;
  Items: TArray<T>;

  function Contains<AItem: T>: Boolean;
end;
Run Code Online (Sandbox Code Playgroud)

当我尝试以这种方式使用它时,出现问题:

TMyRecord = record
  Score: Real;
  A: string;
  B: string;
end;

TMyRecordComparer = class(TComparer<TMyRecord>)
  function Compare(Left, Right: TMyRecord): Integer;
end;

TMyRecordArray = TMyArray<TMyRecord, TMyRecordComparer>;  
Run Code Online (Sandbox Code Playgroud)

有了最后一个声明,我得到以下错误:E2515类型参数'T'与类型'System.Generics.Defaults.TComparer \'不兼容。

任何想法如何解决这个问题?

delphi generics

5
推荐指数
2
解决办法
181
查看次数

64 位相当于 X86 图像处理例程中的 BSWAP

我有一个 Delphi Firemonkey EXIF 实现,我在例程中使用它来加载图像文件。我试图确定图像是否已旋转,以便我可以在显示图像之前纠正图像的方向。该例程部分调用执行 BSWAP 的汇编代码来确定图像文件中标头信息的位置。这是代码的一部分:

type
  TMarker = packed record
    Marker  : Word;      //Section marker
    Len     : Word;      //Length Section
    Indefin : Array [0..4] of Char; //Indefiner - "Exif" 00, "JFIF" 00 and ets
    Pad     : Char;      //0x00
  end;

  TIFDHeader = packed record
    pad       : Byte; //00h
    ByteOrder : Word; //II (4D4D) or MM
    i42       : Word; //2A00 (magic number from the 'Hitchhikers Guide'
    Offset    : Cardinal; //0th offset IFD
    Count     : Word;     // number of IFD entries …
Run Code Online (Sandbox Code Playgroud)

delphi assembly x86-64

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

OS X上的WriteProcessMemory等价物

我在我的图书馆使用方法挂钩/绕行.

由于WriteProcessMemory/ReadProcessMemory是Windows API函数,因此OS X上方法挂钩/绕行的解决方案是什么?

编辑:

好吧,让我在这里提供更多信息,以便更清楚我为什么要问这个问题:

在我的DSharp库的即将推出的功能中,我有以下代码:

procedure FreeInstance(Self: TObject);
begin
  ...

  Self.CleanupInstance;
  FreeMem(Pointer(Self));
end;

var
  FreeInstanceBackup: TXRedirCode;

initialization
  ...
  HookCode(@TObject.FreeInstance, @FreeInstance, FreeInstanceBackup);

finalization
  UnhookCode(@TObject.FreeInstance, FreeInstanceBackup);
  ...

end.
Run Code Online (Sandbox Code Playgroud)

事实是,我需要挂钩到TObject.FreeInstance方法以获得每个对象销毁的通知(是的,我知道,如果有人决定覆盖它并且不调用继承,则可能不会调用它).

另一个使用WriteProcessMemory的单元是ReturnTypePatch.pas,它修复了QC#98687,这对于像我这样的模拟库和来自Vincent Parrett的Delphi Mocks来说不必要的(他们基本上有一个用户在我们都知道这个问题之前报告了这个问题).

WriteProcessMemory的另一个用途是在DSharp的AOP部分中,我基本上用从RTTI的TVirtualMethodInterceptor类创建的代理类VMT替换类的VMT.使用TVirtualMethodInterceptor,您只能代理现有对象 - 我的实现对整个类执行此操作(因此所有现有和将来的对象,即使是继承的).

在所有情况下,使用Move都无法写入内存,因为它们受到保护(在通过调用CopyMemory替换WriteProcessMemory时获取AV).

希望这是关于我正在使用这些功能的足够信息 - 有人可以指出我将在OS X上工作的解决方案(不幸的是我没有,所以我无法测试任何东西).

delphi macos hook delphi-xe2

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

Delphi Spring框架注册泛型类型

使用Delphi Spring框架,是否可以使用GlobalContainter注册泛型类型?我正在尝试做这样的事情:

TMyBaseType = class
protected
  FName: string;
  function GetName: string; virtual;
  procedure SetName(Value: string); virtual;
public
  property Name: string read GetName write SetName;
end;

TMyFirstThing = class(TMyBaseType)
protected
  function GetName: string; override;
end;

TMySecondThing = class(TMyBaseType)
protected
  procedure SetName(Value: string); override;
end;

TMyGenericType<T: TMyBaseType> = class
public
  procedure DoSomethingWithIt(AObject: T);
  function GetTheSomethingsName(AObject: T): string;
end;

// I now want to be able to use the ServiceLocator to get me an instance
// such as TMyGenericType<TMyFirstThing> or TMyGenericType<TMySecondThing>
// but …
Run Code Online (Sandbox Code Playgroud)

delphi generics delphi-2010 spring4d

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

Spring4d:Spring.Collections.IEnumerator和System.IEnumerator

我有一个问题应该是微不足道的,但我找不到任何优雅的答案.

我有一个a的实例,IList<string>我想得到一个逗号分隔的字符串,其中包含所有不同的(不区分大小写)值.

我以为我只是使用string.Join帮助器,因为它有一个很好的重载接受一个IEnumerator<string>as参数.不幸的是,我看到了一个障碍:spring4d重新定义IEnumerator<T>,当然,到处都使用自己的类型.

结果是以下代码无法编译:

var
  distinct: system.IEnumerator<string>;
begin
  result := inherited GetToken;
  if assigned(result) then
  begin
    if not Modules.Contains(STR_DID_SESSION_MODULE) then
      Modules.Add(STR_DID_SESSION_MODULE); 
    distinct := TDistinctIterator<string>.Create(Modules, TIStringComparer.Ordinal);
    result.CustomClaims.Items[STR_CLAIM_CUSTOM_MODULES] := string.Join(',', distinct);
  end;
end;
Run Code Online (Sandbox Code Playgroud)

分配distinct失败E2010 Incompatible types: 'System.IEnumerator<System.string>' and 'Spring.Collections.Extensions.TDistinctIterator<System.string>'

或者,如果我从distinct中删除命名空间,那么对它的调用将string.Join失败.

知道我应该怎么做吗?没有手动遍历迭代并手动执行连接?

delphi spring4d delphi-10.2-tokyo

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

Delphi FreeAndNil:寻找替代实现

注意:请耐心等待,由于此处此处的一些讨论以及我在此处此处报告的一些问题,我感到有点“火爆”

一些背景

Ye olde(10.4 之前)FreeAndNil看起来像这样:

FreeAndNil(var SomeObject)
Run Code Online (Sandbox Code Playgroud)

新的和新鲜的FreeAndNil看起来是这样的:

FreeAndNil(const [ref] SomeObject: TObject);
Run Code Online (Sandbox Code Playgroud)

IMO 都有其缺点:

  • 旧的不做任何类型检查,所以调用FreeAndNil指针、记录和接口编译得很好,但在运行时会产生有趣但通常不需要的效果。(完全狂暴,或者如果幸运的话它会因 EAccessViolation、EInvalidOperation 等而停止。)
  • 新的接受一个 const 参数,因此任何对象。但是随后提供的对象指针实际上是使用一些古怪的代码更改的。
  • 你现在可以FreeAndNil像这样调用新的:FreeAndNil(TObject.Create)它会编译甚至运行得很好。我喜欢FreeAndNil在我出错时警告我并提供例如属性而不是字段的旧版本。不确定如果为此FreeAndNil实现提供对象类型属性会发生什么。没试。

如果我们将签名更改为 ,FreeAndNil(var SomeObject:TObject)那么它将不允许我们传递任何其他变量类型,然后正是该TObject类型。这也是有道理的,好像不是这样FreeAndNil,人们可以轻松地更改TComponent在例程中作为类型提供的变量,将 var 变量更改为完全不同类型的对象,例如TCollection. 当然FreeAndNil不会做这样的事情,因为它总是将 var 参数更改为 nil。

所以这是FreeAndNil一个特例。 甚至可能特别到足以说服 delphi 添加一个编译器魔术 FreeAndNil实现?投票给任何人?

潜在的解决方法 …

delphi memory-management object-lifetime rad-studio delphi-run-time-library

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

如何获得通用类方法的方法地址?

我们可以使用以下代码获取类方法地址:

type
  TMyClass = class
    procedure A;
  end;

var P: Pointer;
begin
  P := @TMyClass.A;
end;
Run Code Online (Sandbox Code Playgroud)

对于泛型类,如何从泛型类获取方法地址?

type
  TGeneric<T> = class
    procedure A;
  end;


var P: Pointer;
begin
  P := @TGeneric<T>.A;  // <--- compilation error
end.
Run Code Online (Sandbox Code Playgroud)

delphi generics

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

德尔福单元测试:为CUT编写一个简单的间谍

我在寻找一种方式来轻松简洁地写为Delphi下DUnitX测试框架间谍.

在过去,我使用非常难看的方式:

[TestFixture]
Test = class(TObject)
public
  [test]
  procedure Test1;
end;

TMyClass = class(TObject)
protected
  procedure MyProcedure; virtual;
end;

TMyTestClass = class(TMyClass)
protected
  fMyProcedureCalled : Boolean;
  procedure MyProcedure; override;
end

procedure TMyTestClass.MyProcedure;
begin
   fMyProcedureCalled := true;
   inherited;
end;

procedure Test.Test1;
var aObj : TMyTestClass;
begin
   TMyTestClass.Create;
   Assert.IsTrue(aObj.fMyProcedureCalled);
end;
Run Code Online (Sandbox Code Playgroud)

所有这些代码都用于检查是否调用了一个过程.那太冗长了!

有没有办法写一个可以帮助我减少代码的间谍?

delphi unit-testing dunit spy dunitx

2
推荐指数
1
解决办法
265
查看次数

In sydney does setting [weak] in front of an object make a penalty?

In delphi sydney, does setting [weak] in front of an object (not an interface) make a penalty ? Exemple :

  TMyObject = class(Tobject)
  Private
    [weak] FOwner: TMyObject;
    ....
  end;
Run Code Online (Sandbox Code Playgroud)

I ask because I know that internally [weak] references are stored in a list and thus it's have some drawbacks (regarding speed). As now with Sydney ARC is gone there is no need anymore to put [weak] in front of an object (as far as I know), but as I want …

delphi firemonkey

2
推荐指数
1
解决办法
136
查看次数

在运行时将对象转换为其父对象

我通过了TObject.我知道这个对象来自TBaseClass.我想要做的是显示每个班级的所有已发布属性,直到TBaseClass.可能有更好的方法来做到这一点,但我正在尝试的是:

lObj := aObject;
while lObj.ClassType <> TBaseClass do
begin
  lRttiType := lRttiContext.GetType(aObject.ClassType);
  lProps := lRttiType.GetDeclaredProperties;

  lStartIdx := Length(lAllProps);
  SetLength(lAllProps, Length(lAllProps) + Length(lProps));

  for I := Low(lProps) to High(lProps) do
    lAllProps[lStartIdx + I] := lProps[I];

  lObj := lObj as lObj.ClassParent;
  // lObj := lObj.ClassParent.InitInstance(lObj); // *see below
end;
Run Code Online (Sandbox Code Playgroud)

这段代码的问题在于lObj.ClassType之后不会改变lObj as lObj.ClassParent.有人可以解释为什么这不起作用并提供一些有用的东西吗?

*这似乎有效,因为它将lObj.ClassType作为父类,但它会导致问题,我后来阅读文档,发现它甚至不应该首先被调用.

delphi casting rtti

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

如何为所有私有/受保护方法生成Rtti信息?

一直在努力解决这个问题,似乎无法找到解决方法.我使用的是Delphi XE-2.

我需要为给定包中的所有类生成私有/受保护方法的Rtti Info.

默认情况下,Delphi似乎只为公共和已发布的方法生成Rtti.

如果我将以下指令添加到包含类的Unit,则为私有和受保护字段生成Rtti,但仅为该类生成.

{$RTTI METHODS([vcPublic, vcProtected, vcPrivate])}
Run Code Online (Sandbox Code Playgroud)

我不想将此指令添加到每个单元.

我将指令添加到Packages .dpk文件中,但它没有任何效果.

谢谢!

delphi rtti compiler-directives delphi-xe2

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

为什么我会收到预期的E2029声明,但发现了'终结'

我没有看到任何语法错误,我的代码编译干净没有完成部分.这是该单元的最后几行.

function boolAsTF(b:boolean): string; inline;
begin
  if b then result := 'T' else result := 'F';
end;

finalization
  SyncMgr.Free;
end.
Run Code Online (Sandbox Code Playgroud)

delphi

0
推荐指数
1
解决办法
762
查看次数