簡體   English   中英

嘗試將跨單元重載的函數導出到.DLL時發生E2276錯誤

[英]E2276 error when attempting to export to .DLL a function overloaded across units

我一直在將有用的例程收集到實用程序單元中,然后將其編譯為.DLL和.DCU,因此我可以選擇哪種方法可以方便地訪問這些例程。

例如,我編寫了自己的Lowcase ,它作用於[寬]字符或[寬]字符串,以實現明顯的功能,而Embarcadero卻沒有實現。

類似地,我擴展了MaxMin以查找數字數組的Max / Min。

在某些情況下,我實際上只是為現有函數提供了一個別名,例如

function LowCase
         (const st                        : ANSIstring
         )                                : ANSIstring;
          stdcall;
begin
  result := ansilowercase(st);
end;

它將通過以下方式導出到DLL

exports LowCase
         (const st                        : ANSIstring
          ) name 'lowcaseansistr';

到現在為止還挺好。

我最近發現

var
  v_uint64 : uint64;

  v_uint64 := $FFFFFFFFFFFFFFFF;
  writeln('v_uint64=',inttostr(v_uint64));
  v_uint64 := $7FFFFFFFFFFFFFFF;
  writeln('v_uint64=',inttostr(v_uint64));

在第一個實例(-1)中產生了不正確的結果-實際上,無論MSB設置在哪里,但是在第二個MSB清除的情況下都可以。

因此,我發現uinttostr並將此標准功能替換為inttostr解決了該問題。

在ISTM中,如果我可以再次簡單地執行別名技巧,那將更加方便,所以我嘗試了(實現)

function inttostr
          (p_nb_int                       : uint64
          )                               : string;
          stdcall;
begin
  result := uinttostr(p_nb_int);
end;

(接口)

function inttostr
          (p_nb_int                       : uint64
          )                               : string;
          overload;
          stdcall;

運作得很愉快,但是實施了

exports inttostr
          (p_nb_int                       : uint64
          ) name 'uinttostr64';

在項目中生成的E2276 Identifier 'IntToStr' cannot be exported E2276似乎與local directive ,顯然是由local;調用的local; 在聲明中-但在EMBT在System.Sysutils.pas中提供的源中,聲明為

function IntToStr(Value: Integer): string; overload;
function IntToStr(Value: Int64): string; overload;

沒有local; 在望!

所以-我很困惑。 我該如何解決? (XE2)


這是一個測試程序:

program countparamsshort;

{$APPTYPE CONSOLE}
{$R *.res}

uses
  dxutypes,
//  dxumethods,
  system.math,windows,vcl.Graphics,classes,System.SysUtils;
//{$I C:\delphi\dxu.inc}

var
  v_int64 : int64 ;           // -2^63..2^63-1
  v_uint64 : uint64;          // 0..2^64-1

procedure showv;
begin
  writeln('v_int64= ',inttostr(v_int64));
  writeln('v_uint64=',inttostr(v_uint64));
end;

begin
  writeln('min values');
  v_int64  := -214748364999;
  v_uint64 := 0;
  showv;
  writeln('max values');
  v_int64  := $FFFFFFFFFFFFFFFF;
  v_uint64 := $FFFFFFFFFFFFFFFF;
  showv;
  writeln('max 63-bit values');
  v_int64  := $7FFFFFFFFFFFFFFF;
  v_uint64 := $7FFFFFFFFFFFFFFF;
  showv;
//  writeln(inttostr(max(10,3)),' & ',inttostr(max([1,12,7,9,11,4])));
  writeln('procedure finished');
  readln;
end.

使用.dcu dxumethods並按原樣運行,並包括文件C:\\ delphi \\ dxu.inc注釋掉將調用inttostrsystem.math實現並生成報告

min values
v_int64= -214748364999
v_uint64=0
max values
v_int64= -1
v_uint64=-1
max 63-bit values
v_int64= 9223372036854775807
v_uint64=9223372036854775807
procedure finished

對於v_uint64這是正確的。 uint64調用uinttostr可以解決問題,但要記住要這樣做。

dxumethods元素中刪除注釋意味着包括我的inttostr版本-實際上執行uinttostr 結果是:

min values
v_int64= -214748364999
v_uint64=0
max values
v_int64= -1
v_uint64=18446744073709551615
max 63-bit values
v_int64= 9223372036854775807
v_uint64=9223372036854775807
10 & 12
procedure finished

現在可以正確顯示v_uint64的值。 這意味着我可以使用inttostr而可以忘記所有有關uinttostr ,因此我不必坐在這里弄清楚什么時候應該使用哪個。 我已經解決了一次,現在編譯器可以在將來完成工作。

我還取消了對MAX調用的注釋,該調用使用相同的方法來查找數組的max -這意味着我可以忘記有關maxintvalue和maxvalue的所有信息(它會調用這些例程),但是我可以再次只需使用max無論是傳統版本還是關於數組的相同概念。 當一個例程可以執行時,不要用三個例程(另外三個用於MIN等效項)使頭腦混亂。

最后,重新注釋dxumethods並取消注釋包含文件,其中包含如下行

function inttostr
      (p_nb_int                       : uint64
      )                               : string;
      overload;
      stdcall;
      external 'dxuproject.dll' name 'uinttostr64';

產生的結果相同,這一次是從.DLL開始的-關鍵是在構造.DLL時限定函數名,否則您會E2276錯誤。

現在-為什么發生這種情況,當圍繞MAX/MIN進行的相似處理不會使編譯器感到困惑時,我將留給理論學家-它與似乎是Kylix宿醉的“本地”聲明有什么關系-嗯,這就是在眾神AFAICS的腿上(或可能是失誤)。

無論如何-好的結果; 問題解決了。 季節的問候...

也許當涉及到重載函數和名稱重整時, Delphi編譯器無法通過Uint64參數告訴Int64 因此,請嘗試精確地指定要導出的功能,而無需依賴自動解析。

  exports UnitName.FunctionName(Params);

我不太了解您的總體目標。 唯一可以導入此類功能的是使用與DLL相同的編譯器構建的Delphi代碼。 該代碼可以直接調用UIntToStr

而且您似乎也正在重新實現RTL已經具有的功能。 例如, AnsiStrings單元將為8位文本提供大小寫轉換功能。 Math ,將為浮點值數組找到MinValue/MaxValue ,為整數數組MinIntValue/MaxIntValue 在我看來,好像您是在重新發明輪子。

就是說,以您的問題為中心,這里是如何導出函數的方法:

library Project1;

uses
  SysUtils;

exports
  UIntToStr(Value: UInt64) name 'uinttostr64';

begin
end.

這將從SysUtils導出函數,因此使用register調用約定。 當然這對您沒有問題,因為您只能從Delphi調用該函數。

如果您急於導出IntToStr ,則應使用標准單元名稱。 例如,假設函數在Unit1聲明,那么您應該編寫:

exports
  Unit1.IntToStr(Value: UInt64) name 'uinttostr64';

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM