我们一直在使用Delphi XE6修复VCL中的错误.到目前为止该文件夹包含:
| VCL Source Fixes
|----- Vcl.ComCtrls.pas
|----- Winapi.CommCtrl.pas
Run Code Online (Sandbox Code Playgroud)
我们将文件夹添加到我们的库搜索路径:

在此过程中,我们了解到我们必须将修复仅限于该implementation部分.否则,该部分中符号的散列签名会发生变化.这会导致链接器意识到DCU内的符号与它们期望的版本不同.interface
巴里凯利对这种行为有一个很好的解释:
符号版本的重要概念.保存DCU时,Delphi根据符号的接口声明计算散列并将其与符号关联.使用该符号的其他单位也存储符号版本.这样,与大多数C链接器不同,避免了由过时符号引起的链接时冲突.
这样做的结果是,您应该能够将Classes.pas添加到您的项目中并几乎根据您的内容修改其实现部分,并且仍然能够静态链接其余的RTL和VCL以及第三方库,甚至仅以对象格式提供的那些.
要小心的事情:
- 内联例程; 内联例程的主体是符号版本的一部分
- 泛型; 泛型类型和方法的实现方是各个符号版本的一部分
因此,我们努力将错误修正限制在实现部分(例如,引入新的cracker类,而不是覆盖面向公众的类中的方法).
然后我去修理了Vcl.Themes.pas.我开始简单,复制文件并将其放在fixes文件夹中:
| VCL Source Fixes
|----- Vcl.ComCtrls.pas
|----- Winapi.CommCtrl.pas
|----- Vcl.Themes.pas
Run Code Online (Sandbox Code Playgroud)
即使我还没有(还)修改过Vcl.Themes.pas,编译器就会对它进行扼流:
[dcc32致命错误] Vcl.Themes.pas(2074):F2051单元Vcl.Forms是用不同版本的Vcl编译的.Themes.TMouseTrackControlStyleHook
重要的问题是:
为什么会这样?
是怎么回事,编译器无法意识到完全相同的文件是完全相同的文件?XE6附带的VCL源是否可能不合适,并且与DCU中的船舶不匹配?它与库搜索顺序有关吗?它是否与内联,泛型,迭代器,平台,调试dcus,64位编译器,ifdef,代码完成,协同作用有关?
还有其他隐含的问题,试图回答原因:
为什么它适用于其他两个文件,但不是这个?
当我甚至没有更改文件时为什么会失败?
VCL Source Fixes在搜索路径中越走越低dcu项目文件夹中的所有文件(尽管没有删除D:\Programs\Embarcadero\Studio\14.0\lib\win32\release\Vcl.Themes.dcuDelphi XE6附带的文件)我有一个脚本可以编译我的解决方案的所有项目(大约50个),如下所示
msbuild "myProjName.dproj" /t:build /p:config="Release" /fileLogger /flp:ErrorsOnly /nologo
Run Code Online (Sandbox Code Playgroud)
这工作得很好,但需要永远编译.为了使构建更快,我一直在尝试利用这里解释的'/ maxcpucount'开关利用现代多核机器的所有潜力:http://msdn.microsoft.com/library/bb651793.aspx
我在我的4核CPU开发机器上得到了相同的编译时间.没有性能上升.
显然,这只能在项目需要构建依赖项时才能工作.然后其他"工人"将并行构建这些依赖项目作为主要项目.所以我试图在delphi中构建一个项目组并将所有项目添加到它中,然后在这个.groupproj上运行msbuild命令,但它仍然像往常一样慢.
有没有人用msbuild同时构建多个项目?如果是,你可以给我一个解释吗?
谢谢!
在Delphi XE6中编译DLL时,它会自动TMethodImplementationIntercept从中导出函数System.Rtti.pas.我试图找到一种方法来避免这种导出,但没有找到任何可以解决问题的配置或编译器指令.
System.Rtti单元几乎无法避免,因为它几乎被delphi中的所有内容间接使用.
在XE6中构建DLL时,有没有办法避免导出此函数?
我正在尝试修复另一个VCL错误 ; 这一次Vcl.Printers.pas.
现在我们通过将错误的VCL源文件复制到Delphi库路径中的另一个文件夹,并将修复程序应用于这些文件来实现此目的.我们将修复程序应用于TPrinter.SetPrinter.
但是文件中有六个方法用属性修饰:
[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinter.Abort;
begin
...
Run Code Online (Sandbox Code Playgroud)
[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinter.EndDoc;
begin
...
Run Code Online (Sandbox Code Playgroud)
[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
procedure TPrinter.NewPage;
begin
...
Run Code Online (Sandbox Code Playgroud)
[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
{$IF DEFINED(CLR)}
procedure TPrinter.SetPrinter(ADevice, ADriver, APort: string; ADeviceMode: IntPtr);
{$ELSE}
procedure TPrinter.SetPrinter(ADevice, ADriver, APort: PChar; ADeviceMode: THandle);
{$ENDIF}
var
...
Run Code Online (Sandbox Code Playgroud)
[PrintingPermission(SecurityAction.LinkDemand, Level=PrintingPermissionLevel.AllPrinting)]
function SetPrinter(NewPrinter: TPrinter): TPrinter;
begin
...
Run Code Online (Sandbox Code Playgroud)
这些方法中的每一种都会引发警告:
我可以删除属性.或者可能有一种方法可以抑制警告.但我认为Embarcadero增加的属性有一些目的.
我正在尝试解决System.Classes.pas中一个已知的丑陋性能限制,它具有20世纪80年代的常量缓冲区限制($ F000),如下所示:
function TStream.CopyFrom(const Source: TStream; Count: Int64): Int64;
const
MaxBufSize = $F000;
....
Run Code Online (Sandbox Code Playgroud)
这导致我们的Delphi应用程序遭受重大性能损失.在delphi XE2到XE5中,我们能够修改它并使用以下方法之一:
我可以修改Delphi源代码,然后通过从批处理文件调用dcc32.exe,重建Delphi库文件夹中的System.Classes.dcu文件.我意识到这很难看,我不喜欢这样做,但我不喜欢RTL中这个丑陋的性能问题,而且我们的用户无法忍受它带来的性能问题.
我可以尝试在我的项目搜索路径中的某处放置一个经过修改的system.classes.pas文件.
现在,在Delphi XE6中,上述两种方法都不适合我,这可能要归功于一些内部编译器的更改.我在其uses子句中包含System.Contnrs的最小命令行应用程序中得到的错误是:
[dcc32 Fatal Error] System.Classes.pas(19600): F2051 Unit System.Contnrs was compiled with a different version of System.Classes.TComponent
Run Code Online (Sandbox Code Playgroud)
重现此问题的示例程序(假设您已修改了System.Classes.pas并更改了MaxBufSize常量),如下所示:
program consoletestproject;
{$APPTYPE CONSOLE}
{$R *.res}
uses
System.Contnrs,
System.SysUtils;
var
List:System.Contnrs.TObjectList;
begin
WriteLn('Hello world');
end.
Run Code Online (Sandbox Code Playgroud)
同样,这个问题在Delphi XE6中很容易重现,但在XE5或更早版本中不是问题.
当您绝对必须使用System.Classes.pas或System.SysUtils.pas或其他一些非常低级别单元的修改副本解决基本RTL或VCL限制时,建议的做法是什么?(是的,我知道如果你不必这样做,你就不应该这样做,不要为讲课而烦恼.)
是否有一组神奇的命令行参数可以通过命令行中的"dcc32.exe"使用,以生成一个修改后的DCU,它将与上面的应用程序示例正确链接?
作为第二个问题,是否有.dcu文件没有源存在,当一个人尝试这样做时会破坏,在这种情况下,上述所有的答案是,"你无法解决这个问题,如果有一个bug在RTL中,你运气不好"?
一种可能的解决方法是在项目搜索路径(或库路径)中包含"$(BDS)\ source\rtl\common",强制每个损坏的(需要重新编译)DCU重建每个时间,但这看起来很丑陋和错误.
我是Firemonkey和Android的新手,我不知道我的方法是否错误.我希望有一个应用程序运行并读取NFC标签.
有没有办法在带有firemonkey的Android设备中使用NFC阅读器?
使用FMXExpress的NFCAdapter的一部分(http://www.fmxexpress.com/full-android-sdk-interface-files-in-object-pascal-for-firemonkey/),我可以确定该设备是否具有NFC读卡器如果它已启用.但是要使用所有函数,我必须手动定义所有接口并解决所有循环引用.我不认为这可以导致一个探针解决方案.
我正面临着构建我自己的JavaClass以与nfc适配器通信的解决方案,如本博客文章所述:http://blong.com/Articles/DelphiXE5AndroidActivityResult/ActivityResult.htm#Building
我有这个问题.当我隐藏我的主窗体时,我的应用程序的任务栏图标也被隐藏.我也看到了一个关于这个问题的新问题,答案并没有真正帮助.他们建议尽量减少它,但我不想最小化应用程序.
应用程序运行时是否可以更改主窗体?
例如.我有两种形式.当我想隐藏一个表单并显示另一个表单时,任务栏图标应保留在任务栏上,主表单应切换到另一个表单.
我使用的是Delphi XE6,它是一个VCL Forms应用程序.
我还看到了一个关于在运行时更改主窗体的一个不同的老问题,但它很老,仍然基于Delphi 6.
我读过的所有内容都表明TRTTIContext是线程安全的.
但是,当多线程时,TRTTIContext.FindType似乎偶尔会失败(返回nil).在它周围使用TCriticalSection可以解决问题.请注意,我正在使用XE6,并且XE中似乎不存在该问题.编辑:似乎存在于所有具有新RTTI单元的Delphi版本中.
我已经编写了一个测试项目,你可以用来亲自看看.创建一个新的VCL项目,删除TMemo和TButton,用下面替换unit1,并分配Form1.OnCreate,Form1.OnDestroy和Button1.OnClick事件.密钥CS是TTestThread.Execute中的GRTTIBlock.目前已禁用,当我运行200个线程时,我得到3到5个失败.启用GRTTIBlock CS可以消除故障.
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, SyncObjs, Contnrs, RTTI;
type
TTestThread = class(TThread)
private
FFailed: Boolean;
FRan: Boolean;
FId: Integer;
protected
procedure Execute; override;
public
property Failed: Boolean read FFailed;
property Ran: Boolean read FRan;
property Id: Integer read FId write FId;
end;
TForm1 = class(TForm)
Memo1: TMemo;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
FThreadBlock: TCriticalSection;
FMaxThreadCount: Integer;
FThreadCount: Integer; …Run Code Online (Sandbox Code Playgroud) 目标是在单个Delphi应用程序中将浮点数转换为字符串,以实现可用内核的完全使用.我认为这个问题适用于字符串的一般处理.然而在我的例子中,我特意使用FloatToStr方法.
我正在做什么(我保持这个非常简单,所以在实现方面几乎没有含糊之处):
虽然使用了多个内核,但CPU使用率%总是最大限度地取决于单个内核的数量.我知道这是一个既定问题.所以我有一些具体的问题.
以简单的方式,可以通过多个应用实例来完成相同的操作,从而实现对可用CPU的更充分利用.是否可以在同一个可执行文件中有效地执行此操作?即在OS级别上分配线程不同的进程ID或OS识别的某些等效分区?或者这是开箱即用的Delphi无法实现的?
在范围上:我知道有不同的内存管理器和其他组已经尝试更改一些较低级别的asm锁使用http://synopse.info/forum/viewtopic.php?id=57 但是,我在问这个问题在如此低的水平上不做事的范围.
谢谢
嗨J.我的代码故意很简单:
TTaskThread = class(TThread)
public
procedure Execute; override;
end;
procedure TTaskThread.Execute;
var
i: integer;
begin
Self.FreeOnTerminate := True;
for i := 0 to 1000000000 do
FloatToStr(i*1.31234);
end;
procedure TfrmMain.Button1Click(Sender: TObject);
var
t1, t2, t3: TTaskThread;
begin
t1 := TTaskThread.Create(True);
t2 := TTaskThread.Create(True);
t3 := TTaskThread.Create(True);
t1.Start;
t2.Start;
t3.Start;
end;
Run Code Online (Sandbox Code Playgroud)
这是一个"测试代码",其中CPU(通过性能监视器)最大值为25%(我有4个内核).如果将FloatToStr线路交换为非字符串操作,例如Power(i,2),则性能监视器会显示预期的75%使用率.(是的,有更好的方法来衡量这一点,但我认为这对于这个问题的范围是足够的)
我已经相当彻底地探讨了这个问题.问题的目的是以非常简单的形式提出问题的关键.
我在询问使用FloatToStr方法时的限制.并且询问是否存在可以更好地使用可用内核的实现化身.
谢谢.
我想将我的字符串拆分为数组但是当最后一个"值"为空时它会很糟糕.请看我的例子.是bug还是功能?有没有办法如何使用此功能没有解决方法?
var
arr: TArray<string>;
arr:='a;b;c'.Split([';']); //length of array = 3, it's OK
arr:='a;b;c;'.Split([';']); //length of array = 3, but I expect 4
arr:='a;b;;c'.Split([';']); //length of array = 4 since empty value is inside
arr:=('a;b;c;'+' ').Split([';']); //length of array = 4 (primitive workaround with space)
Run Code Online (Sandbox Code Playgroud)