标签: delphi-xe6

F2051:单位%s使用不同版本的%s编译

我们一直在使用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在搜索路径中越走越低
  • 尝试打开使用调试dcus
  • 尝试切换到64位平台
  • 尝试删除dcu项目文件夹中的所有文件(尽管没有删除D:\Programs\Embarcadero\Studio\14.0\lib\win32\release\Vcl.Themes.dcuDelphi XE6附带的文件)
  • 关闭XE6并重新运行它 …

delphi delphi-xe6

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

通过MSBuild并行编译delphi项目

我有一个脚本可以编译我的解决方案的所有项目(大约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 msbuild delphi-xe6

13
推荐指数
2
解决办法
1900
查看次数

Delphi XE6 DLL:不需要的导出:TMethodImplementationIntercept

在Delphi XE6中编译DLL时,它会自动TMethodImplementationIntercept从中导出函数System.Rtti.pas.我试图找到一种方法来避免这种导出,但没有找到任何可以解决问题的配置或编译器指令.

System.Rtti单元几乎无法避免,因为它几乎被delphi中的所有内容间接使用.

在XE6中构建DLL时,有没有办法避免导出此函数?

delphi dll rtti delphi-xe6

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

Vcl.Printers.pas(888):W1025不支持的语言功能:'自定义属性'

我正在尝试修复另一个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)

这些方法中的每一种都会引发警告:

  • [dcc32警告] Vcl.Printers.pas(968):W1025不支持的语言功能:'自定义属性'
  • [dcc32警告] Vcl.Printers.pas(978):W1025不支持的语言功能:'自定义属性'
  • [dcc32警告] Vcl.Printers.pas(1015):W1025不支持的语言功能:'自定义属性'
  • [dcc32警告] Vcl.Printers.pas(1026):W1025不支持的语言功能:'自定义属性'
  • [dcc32警告] Vcl.Printers.pas(1080):W1025不支持的语言功能:'自定义属性'
  • [dcc32警告] Vcl.Printers.pas(1599):W1025不支持的语言功能:'自定义属性'

我可以删除属性.或者可能有一种方法可以抑制警告.但我认为Embarcadero增加的属性有一些目的.

  • 使语言支持功能自定义属性的方法是 …

delphi delphi-xe6

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

我可以修改RTL类System.Classes.TStream中的常量并在运行时在Delphi XE6中重建它吗?

我正在尝试解决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重建每个时间,但这看起来很丑陋和错误.

delphi delphi-xe6

11
推荐指数
2
解决办法
957
查看次数

Firemonkey安卓NFC适配器

我是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 android nfc firemonkey delphi-xe6

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

Delphi在应用程序运行时更改主窗体

我有这个问题.当我隐藏我的主窗体时,我的应用程序的任务栏图标也被隐藏.我也看到了一个关于这个问题的新问题,答案并没有真正帮助.他们建议尽量减少它,但我不想最小化应用程序.

应用程序运行时是否可以更改主窗体?

例如.我有两种形式.当我想隐藏一个表单并显示另一个表单时,任务栏图标应保留在任务栏上,主表单应切换到另一个表单.

我使用的是Delphi XE6,它是一个VCL Forms应用程序.

我还看到了一个关于在运行时更改主窗体的一个不同的老问题,但它很老,仍然基于Delphi 6.

forms delphi vcl taskbar delphi-xe6

10
推荐指数
3
解决办法
9629
查看次数

TRTTIContext多线程问题

我读过的所有内容都表明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 multithreading win64 rtti delphi-xe6

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

并行处理字符串Delphi完全可用的CPU使用率

目标是在单个Delphi应用程序中将浮点数转换为字符串,以实现可用内核的完全使用.我认为这个问题适用于字符串的一般处理.然而在我的例子中,我特意使用FloatToStr方法.

我正在做什么(我保持这个非常简单,所以在实现方面几乎没有含糊之处):

  • 使用Delphi XE6
  • 创建从TThread继承的线程对象,并启动它们.
  • 在线程执行过程中,它将通过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方法时的限制.并且询问是否存在可以更好地使用可用内核的实现化身.

谢谢.

delphi parallel-processing multithreading delphi-xe6

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

当最后一个值为空时,String.Split工作很奇怪

我想将我的字符串拆分为数组但是当最后一个"值"为空时它会很糟糕.请看我的例子.是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)

delphi delphi-xe6

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