【问题标题】:Unable to use C's .OBJ files compiled by cl.exe in Delphi XE4 Win64 platformDelphi XE4 Win64平台无法使用cl.exe编译的C的.OBJ文件
【发布时间】:2014-09-12 23:17:42
【问题描述】:

我想将 7Zip 的 SDK 翻译成 Delphi/Pascal 的单元文件。首先,我尝试使用 BCC32.exe 为 Win32 平台编译 C 文件:

bcc32.exe -c -D_LZMA_PROB32 -D_WIN32 -v -y Threads.c LzFind.c LzFindMt.c LzmaDec.c LzmaEnc.c

它生成的.OBJ 文件很少,我可以毫无问题地在 Delphi 单元中使用这些对象。

unit Threads;

interface

uses System.Win.Crtl, Winapi.Windows, LzmaTypes, System.Classes;

{$Z4}
type
  TCEvent = THandle;

  TCSemaphore = THandle;

  TCCriticalSection = TRTLCriticalSection;

  TCAutoResetEvent = TCEvent;

  TCThread = THandle;

  TThread_Func_Type = Pointer;

function __beginthreadex(__security_attr: Pointer; __stksize: Cardinal; __start:
    TThread_Func_Type; __arg: Pointer; __create_flags: Cardinal; var
    __thread_id: Cardinal): Cardinal; cdecl; external msvcrt name _PU +
    '_beginthreadex';

function _Event_Reset(var p: TCEvent): TWRes; cdecl; external name _PU +
    'Event_Reset';

function _Event_Set(var p: TCEvent): TWRes; cdecl; external name _PU +
    'Event_Set';

function _Handle_WaitObject(h: THandle): TWRes; cdecl; external name _PU +
    'Handle_WaitObject';

function _Semaphore_Release1(var p: TCSemaphore): TWRes; cdecl; external name
    _PU + 'Semaphore_Release1';

function _HandlePtr_Close(var h: THandle): TWRes; cdecl; external name _PU +
    'HandlePtr_Close';

function _CriticalSection_Init(var p: TCCriticalSection): TWRes; cdecl; external
    name _PU + 'CriticalSection_Init';

function _AutoResetEvent_CreateNotSignaled(var p: TCAutoResetEvent): TWRes;
    cdecl; external name _PU + 'AutoResetEvent_CreateNotSignaled';

function _Semaphore_Create(var p: TCSemaphore; initCount: UInt32; maxCount:
    UInt32): TWRes; cdecl; external name _PU + 'Semaphore_Create';

function _Thread_Create(var p: TCThread; func: TThread_Func_Type; param:
    LPVOID): TWRes; cdecl; external name _PU + 'Thread_Create';

implementation

{$ifdef Win64}
  {$L Win64\Threads.o}
{$else}
  {$L Win32\Threads.obj}
{$endif}

end.

然后我尝试使用 BCC64.exe 为 Win64 平台编译这些目标文件:

bcc64.exe -c -D_LZMA_PROB32 -D_WIN64 -v -y Threads.c LzFind.c LzFindMt.c LzmaDec.c LzmaEnc.c

这一次,它产生了很少的.o 文件,但是在编译 Delphi 单元时出现错误:

[dcc64 Fatal Error] LzFind.pas(128): F2084 Internal Error: AV0756F5D3-R2D06DB90-0

我了解到 Delphi Win64 识别的目标文件格式是 64 位 COFF,而 BCC64.exe 生成 ELF64 格式。

然后我尝试使用 Microsoft Windows SDK 中的 cl.exe 来生成 Win32 和 Win64 .OBJ 文件,

cl.exe -c -D_LZMA_PROB32 -D_WIN32 Threads.c LzFind.c LzFindMt.c LzmaDec.c LzmaEnc.c

x86_amd64\cl.exe -c -D_LZMA_PROB32 -D_WIN64 Threads.c LzFind.c LzFindMt.c LzmaDec.c LzmaEnc.c

但我收到以下错误:

[dcc32 Error] Threads.pas(64): E2065 Unsatisfied forward or external declaration: '__imp__CloseHandle@4'
[dcc32 Error] Threads.pas(64): E2065 Unsatisfied forward or external declaration: '__imp__GetLastError@0'
[dcc32 Error] Threads.pas(64): E2065 Unsatisfied forward or external declaration: '__imp__InitializeCriticalSection@4'

任何想法如何使用cl.exe 生成可以由Delphi 单元在Win32 和Win64 平台上编译的.OBJ 文件?

【问题讨论】:

  • 我使用 cl 生成与$LINK 静态链接的对象。我看不到您是如何尝试这样做的,因此我无法告诉您出了什么问题。很难知道你为什么问这个问题,但忽略了所有关键细节。您为 bcc32 和 bcc64 提供了命令行,但没有为 cl 提供命令行,这就是您要问的!第 1 步是让一个简单的功能起作用。 int sum(int x1, int x2) { return x1 + x2; } 一旦你能做到这一点,让它变得更复杂。
  • FWIW,当我这样做时,我对 32 位对象使用 bcc32,对 64 位对象使用 cl。在我看来,您的错误似乎来自 32 位 Delphi 编译器。我建议您继续使用 32 位的 bcc32。
  • @DavidHeffernan:我编辑主题并添加 Delphi 示例和 cl.exe 编译选项。
  • 既然您已经有了一个适用于 32 位的解决方案,为什么要改变它呢?就目前而言,我什至不确定您是在询问 32 位还是 64 位。
  • FWIW,我听说,从尝试过这个的人那里(但我自己没有证实这一点),XE6 可以消耗 64 位 COFF 和 64 位 ELF 文件。

标签: delphi coff cl.exe


【解决方案1】:

有点混乱,但是在Delphi中,

  • 对于 64 位,您可以使用由例如 Microsoft 的 64 位编译器生成的 64 位 COFF 文件。据报道,Delphi XE6 64 位也能够链接 64 位 ELF 文件,因为 C++Builder 64 位会生成它们。

  • 对于 32 位,您可以使用由 C++Builder 生成的 32 位 OMF C 目标文件。 Delphi XE2 和更新版本(参见 David Heffernan 的评论中的 this link)也允许您链接到 32 位 COFF。

有关该主题的更多信息:Using C object files in Delphi

所以从 Delphi XE6 开始,您实际上可以使用 C++Builder 再次为两个平台生成 Delphi 可链接的目标文件。

【讨论】:

  • 有没有一种简单的方法可以为 Win32 和 Win64 平台构建 Delphi 单元?在声明中添加_PU 似乎还不够。
  • 奇怪的是,人们投票赞成明显错误的答案。可惜点赞真的很奇怪。也许收集代表的最佳策略是写下错误的答案作为同情投票者的诱饵。投反对票的目的不是讨厌别人,而是鼓励他们更正或删除他们的答案。当鲁迪意识到自己的错误时,他当然会改正。我会删除反对票,一切都会好起来的。
  • 第二个要点。在链接的问题中完整阅读艾伦的答案。
  • 第二个要点有什么问题?大多数 Delphi 版本需要 32 位 OMF 文件,但最新版本(不确定 XE4 是否也是如此)也允许使用 32 位 COFF 文件。请注意,它们必须是 C 目标文件,即使用 C 编译器编译(通常通过为源文件提供扩展名 .c 来实现)。
  • @DavidHeffernan:好的,我稍微重新排列了文本,并将关于 32 位 COFF 的语句拉到项目符号中。
猜你喜欢
  • 2013-07-21
  • 2014-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-12
  • 1970-01-01
  • 2013-11-20
  • 1970-01-01
相关资源
最近更新 更多