我一直在将有用的例程收集到一个实用程序单元中,然后我将其编译成.DLL和.DCU,因此我可以选择哪种方法可以方便地访问这些例程。
例如,我编写了自己的 Lowcase ,它作用于[宽]字符或[宽]字符串以实现明显的功能,奇怪的是Embarcadero没有实现。
同样,我扩展了 Max 和 Min 来查找数字数组的最大值/最小值。
在某些情况下,我基本上只是为现有函数提供了一个别名,例如
function LowCase
(const st : ANSIstring
) : ANSIstring;
stdcall;
begin
result := ansilowercase(st);
end;
将通过
导出到DLLexports 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 注释掉 system.math inttostr
与结果报告的实施
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
,不更正。为uinttostr
调用uint64
可以解决问题,但这意味着要记住这样做。
从 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
错误。
现在 - 为什么会发生这种情况,当MAX/MIN
周围的类似阴谋不会扰乱编译器时,我会留给理论家 - 以及它与“本地”声明有什么关系,这似乎是一个Kylix宿醉 - 嗯,那是在神AFAICS的圈数(或者可能是失效)。
无论如何 - 好结果;问题解决了。季节的问候......
答案 0 :(得分:2)
也许当涉及到重载函数和名称修改 Delphi编译器无法从Int64
参数告诉Uint64
。因此,请尝试精确指定您要导出的函数,而不依赖于自动解析。
exports UnitName.FunctionName(Params);
答案 1 :(得分:0)
我无法理解你的总体目标。唯一可以导入这样一个函数的东西是使用与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';