Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/delphi/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在不更改库文件的情况下修改Delphi库文件中的常量?_Delphi_Constants_Delphi 10 Seattle - Fatal编程技术网

如何在不更改库文件的情况下修改Delphi库文件中的常量?

如何在不更改库文件的情况下修改Delphi库文件中的常量?,delphi,constants,delphi-10-seattle,Delphi,Constants,Delphi 10 Seattle,我使用第三方库,需要为其更改常量。我想在不覆盖文件的情况下自定义库。 pas文件是库文件,不是可继承的类 目前我可以通过编辑文件来实现我的目标 unit libraryconstants; interface uses System.Types; const constant1 = 'foo'; constant2 = 32; constant3: Integer = 12; constant4: TSize = (cx: 32; cy: 32); 不知何故,我需要像

我使用第三方库,需要为其更改常量。我想在不覆盖文件的情况下自定义库。 pas文件是库文件,不是可继承的类

目前我可以通过编辑文件来实现我的目标

unit libraryconstants;

interface

uses
  System.Types;

const
  constant1 = 'foo';
  constant2 = 32;
  constant3: Integer = 12;
  constant4: TSize = (cx: 32; cy: 32);
不知何故,我需要像这样更改constant4:

constant4: TSize = (cx: 16; cy: 8);
我可以编辑libraryconstants.pas并保存它,但当我更新库时(因为发布了新版本),我将丢失此更改。当然,我可以在每次更新库时提醒我应用此更改,但如果可能的话,我希望避免这样做

由于常数不是已发布的属性,我不知道如何获得所需的结果。我希望尽可能少地干扰库代码

我正在寻找一个德尔福语言的“把戏”,我不知道

谢谢。

在项目设置中(CTRL+SHIFT+F11):

将“可赋值类型常量”的值更改为True。 然后,您可以将类型化常量修改为常规变量:

constant4.cx := 16;
constant4.cy := 8;
制作一个新单元:

unit libraryconstantspatch;

interface

implementation

uses System.Types, libraryconstants;

initialization

asm
        mov     eax,offset libraryconstants.constant4
        mov     [eax+offset TSize.cx],16
        mov     [eax+offset TSize.cy],8
end

finalization

end.

然后在应用程序中的libraryconstants单元之后的USES语句中列出此单元。

我错误地认为键入的常量存储在只读内存中,就像它们在其他语言中一样。事实并非如此。因此,您可以通过指针访问这个类型化常量,从而非常轻松地更改它的值

PSize(@constant4).cx := 16;
PSize(@constant4).cy := 8;
将此代码添加到一个单元的初始化部分。在执行任何依赖于该常量的代码之前,您需要确保它运行得足够早,以实现更改

我认为我的误解是因为知道字符串文本存储在只读存储器中。所以我假设类型化常量也是如此。我怀疑,当添加可分配类型化常量“特性”时,编译器开关只是使编译器拒绝对类型化常量的写入,而不是将它们移动到只读内存中


请注意,我所说的只读内存在桌面编译器上是正确的。我不确定这在移动编译器上是否属实。这段代码很可能会在移动编译器上出现运行时内存保护错误而失败。在这种情况下,您需要在写入之前临时更改内存保护。

我的建议:不要更改常量,更改方法

检查使用常量的方法(过程或函数),然后使用新常量“重载”该方法

如果它在类中,只需继承该类,并使用新名称仅修改该方法,如过程“aMethod_size2”。名称size2正在对此进行标记


据我所知,这是惯例。

该常数存储在只读存储器中。在启动时,例如在单元初始化中,将内存保护设置为可写。修改内存,恢复内存保护。@DavidHeffernan-不错的黑客,即使它违反了所有规则…@DavidHeffernan你有样本吗?谢谢。我会继续修补源代码,而不是在运行时修补。您可以通过常用代码路径中的断言提醒自己。将版本控制与“供应商分支”一起使用(这正是它的用例):除非原始源代码包含{$J-}编译器指令(或将来获得一个)。绝对不建议为整个项目启用可分配类型常量。这是一个仅为与旧代码兼容而偶然存在的设置。您绝对不应该使用它。@David不建议使用它,因为更改常量是个坏主意。但问题中提出了这一点。如果我必须在黑客攻击(更改内存保护状态->不仅该常量可写,…)和编译器设置之间进行选择,我更愿意更改项目的编译器选项。您只需要临时更改保护。它可以恢复。碰巧我对保护的看法是错误的。类型化常量不受保护。但无论如何,即使它们是,启用类型化常量也是一个糟糕的主意。嗯,显然我是。我不敢相信Emba弄错了。不过,asm是个坏主意。使用
TSize((@constant4)^).cx:=16;TSize((@constant4)^).cy:=8PSize(@constant4).cx := 16;
PSize(@constant4).cy := 8;