Clarion 6.3 DLL,* CSTRING参数导出功能-添加不可见的参数吗?

问题描述 投票:0回答:1

我需要从我的Delphi应用程序中协商一个函数调用,并调用Clarion 6.3中提供的DLL。我需要传递一个或两个字符串参数(一个函数或两个参数或两个单参数函数)。我们很快就决定使用1字节的0尾字符串(C术语为char*,Clarion术语为CSTRING,Delphi术语为PAnsiChar),在这里事情变得有些不可预测且难以理解。 >

我们得到的有效解决方案是传递伪装成32位整数的无类型指针,然后Clarion制作的DLL使用Clarion程序员称为“ pick”或“ peek”的指针遍历内存。在Clarion和Visual Basic之间的互操作上也有论坛文章,讨论了将字符串从VB传递到Clarion并瞥了一眼Clarion开发人员在我的肩膀上说:“我不需要它的副本,我已经知道了,是典型的”。

但是,从长远来看,这给我们带来了更多负担,因为底层的无类型代码在样板上容易得多,而且容易出错。输入代码将是更好的解决方案。

我在这里寻求的不是“复制粘贴并使事情在没有思考的情况下工作的模式”-我们已经有了它-而更多的是了解,幕后发生的事情以及如何依靠它,我应该对Clarion DLL有什么期望。为了避免最终陷入“偶然的工作”解决方案中。

[当我从肩膀后面看向Clarion 6.3的帮助时,该帮助并不适合低级的细节。这完全是关于从Clarion调用DLL,而不是被调用。我的机器上也没有Clarion,我不想,借用它。而且据我所知,Clarion 6.3运行时的源代码也对开发人员不可用。

[Clarion与VB之间或Clarion与C#之间的互操作之类的文章没有帮助,因为它们融合了两种语言的特质,而提供的有关“裸机”级别的信息却很少。

[Google图书指向“ Clarion技巧与技巧-David Harms”-对于Clarion经验丰富的人似乎有有趣的见解,但我是Clarion零。至少我不能从中找出底层互操作的细节。

[也许有一种方法可以使Clarion 6.3为它生成的DLL保存“列表文件”,也许是标准的* .H头文件?


因此,重复一遍,按预期工作的是一个在Delphi端传递指针的函数(procedure ...(const param1, param2: PAnsiChar); stdcall;,应将其转换为C stdcall void ...(char* p1, char* p2),并且据称在Clarion中看起来像(LONG, LONG), LONG, pascal, RAW

此函数以相反的顺序从堆栈中获取两个32位参数,使用它们,然后退出,在EAX寄存器中传递返回值(实际上是未使用的垃圾),并从堆栈中清除参数。几乎完全是stdcall,只是出于某些晦涩的原因似乎保留了EBX寄存器。

号角功能输入:

04E5D38C 83EC04           sub esp,$04        ' allocate local vars
04E5D38F 53               push ebx           '  ????????
04E5D390 8B44240C         mov eax,[esp+$0c]
04E5D394 BBB4DDEB04       mov ebx,$04ebddb4
04E5D399 B907010000       mov ecx,$00000107
04E5D39E E889A1FBFF       call $04e1752c     ' clear off local vars before use

及其出口

00B8D500 8B442406         mov eax,[esp+$06] ' pick return value
00B8D504 5B               pop ebx           ' ????
00B8D505 83C41C           add esp,$1c       ' remove local vars
00B8D508 C20800           ret $0008         ' remove two 32-bits params from stack

除了我无法解释的使用EBX的操作并返回垃圾结果-它按预期工作。但是-需要在Clarion源中进行无类型的低级操作。

现在据称仅使用一个字符串参数的函数:在Delphi侧-procedure ...(const param1: PAnsiChar); stdcall;,应转换为C stdcall void ...(char* p1),并据称在Clarion中看起来像(*CSTRING), LONG, pascal, RAW

号角功能输入:

00B8D47C 83EC1C           sub esp,$1c    ' allocate local vars
00B8D47F 53               push ebx       '  ????????
00B8D480 8D44240A         lea eax,[esp+$0a]
00B8D484 BB16000000       mov ebx,$00000016
00B8D489 B990FEBD00       mov ecx,$00bdfe90
00B8D48E BA15000000       mov edx,$00000015
00B8D493 E82002FBFF       call $00b3d6b8 ' clear off local vars before use

及其出口

04E5D492 8B442404         mov eax,[esp+$04]  ' pick return value
04E5D496 5B               pop ebx            ' ????
04E5D497 83C404           add esp,$04        ' remove local vars
04E5D49A C20800           ret $0008          ' remove TWO 32-bits params from stack

这里令人震惊的是,该函数希望以某种方式获得两个参数,并且仅使用第二个参数(在x86 asm代码中,我没有看到对第一个参数的任何引用)。如果将其称为procedure ...(const garbage: integer; const param1: PAnsiChar); stdcall;,该函数似乎可以正常工作,该函数应转换为C stdcall void ...(int garbage, char* p1)

此“不可见”参数在面向对象的语言方法函数中看起来很像Self / This指针,但是Clarion程序员确定地告诉我没有任何对象。更重要的是,他的'double-int'函数似乎也不希望使用不可见的参数。

[上述“技巧”书将&CSTRING&STRING号角类型描述为实际上是背后的两个参数,即指向缓冲区的指针和缓冲区的长度。但是,它没有提供有关它们如何在堆栈上传递的具体信息。但是我说Clation拒绝使用导出的&CSTRING参数化的函数制作DLL。

我可以假设不可见的参数是Clarion想要存储函数的返回值的地方(如果在Clarion源代码中有对它的任何赋值),这违反了stdcall / PASCAL约定,但是汇编器结尾代码显示了清楚的用法的EAX寄存器,然后再次使用'double-LONG'函数。

并且,因此,当我制作“在我的机器上工作”质量代码时,通过自愿插入垃圾参数成功调用了Clarion函数-我感到很模糊,因为我无法理解Clarion在做什么以及为什么这样做因此,在任何看似无关的更改之后,它将来可能突然开始做些什么。

那个不可见参数是什么?为什么会在那里发生?可以期待什么?

我需要从我的Delphi应用程序中协商一个函数调用,并调用Clarion 6.3中提供的DLL。我需要传递一个或两个字符串参数(一个函式和两个参数或两个单参数...

string dll calling-convention stdcall clarion
1个回答
0
投票

如果您消费

© www.soinside.com 2019 - 2024. All rights reserved.