我一直在将有用的例程收集到一个实用程序单元中,然后我将其编译成.DLL和.DCU,因此我可以选择哪种方法可以方便地访问这些例程 .
例如,我编写了自己的 Lowcase ,它作用于[宽]字符或[宽]字符串以实现明显的功能,奇怪的是Embarcadero没有实现 .
同样,我扩展了 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;
调用 - 但是在System.Sysutils.pas中由EMBT提供的源中,声明是
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注释掉调用 inttostr
的system.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
哪个 NOT 对于 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等价的另外3个)混淆思维 .
最后,重新评论dxumethods并取消注释包含文件的包含文件
function inttostr
(p_nb_int : uint64
) : string;
overload;
stdcall;
external 'dxuproject.dll' name 'uinttostr64';
产生了相同的结果,这次来自.DLL - 关键是在构造.DLL时限定函数名,否则你会错过 E2276
错误 .
现在 - 为什么会发生这种情况,当这些事情发生在理论家身上时 - 以及它与'local'声明似乎是一个Kylix宿醉的事情 - 好吧,那是在众神的圈数(或者可能是失效) AFAICS .
无论如何 - 好结果;问题解决了 . 季节的问候...
2 回答
也许当涉及到重载函数和名称错误时,Delphi编译器无法告诉
Int64
来自Uint64
参数 . 因此,请尝试精确指定您要导出的函数,而不依赖于自动解析 .我不太明白你的总体目标 . 唯一可以导入这样一个函数的东西是使用与DLL相同的编译器构建的Delphi代码 . 而且该代码可以直接调用
UIntToStr
.而且您似乎也在重新实现RTL已经具有的功能 . 例如,
AnsiStrings
单元将为8位文本提供案例切换功能 . 在Math
中,您会发现MinValue/MaxValue
表示浮点值数组,而MinIntValue/MaxIntValue
表示整数数组 . 它看起来好像你正在重新发明轮子 .也就是说,从表面上看问题,以下是导出函数的方法:
这将从
SysUtils
导出函数,因此使用register
调用约定 . 当然,这对你来说没问题,因为你只能从Delphi调用这个函数 .如果您急于导出
IntToStr
,那么您应该使用完全合格的单位名称 . 例如,假设函数在Unit1
中声明,那么你会写: