如何在不更改库文件的情况下修改Delphi库文件中的常量?
我使用第三方库,需要为其更改常量。我想在不覆盖文件的情况下自定义库。 pas文件是库文件,不是可继承的类 目前我可以通过编辑文件来实现我的目标如何在不更改库文件的情况下修改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); 不知何故,我需要像
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:=8使用ASM的原因是,如果常量是在{$J-}状态下定义的,则不能直接使用PASCAL对其进行修改,但可以通过ASM进行修改。呃,我前面评论中的代码说明了如何做到这一点,我不会称之为“直接”。“Directly”将是常量4.cx:=16;你认为asm更好吗?真正地跨平台呢?这真是新闻。非常感谢,它工作得很好。
PSize(@constant4).cx := 16;
PSize(@constant4).cy := 8;