[疑难] D的调用协议

player7 2007-08-23
问题如下:我调用HGE.dll里的函数

在HGE的C++头文件中,有这样的虚函数

virtual void __STDCALL System_Log(const char *format, ...) = 0;

我把它直接翻译成了:
extern(Windows) void System_Log(char *format, ...);

一直用了很长时间也没啥问题,但是今天才想起来STDCALL是怎么实现可变参数的啊???
这样的话,D里面的 Windows 调用协定能和它共同工作吗???
achun 2007-08-23
查了一下:
_stdcall是Windows API函数中默认的调用约定.
extern(Windows)正好呼应,
_stdcall将参数压栈是按C语言的顺序(从右到左),但与C 语言不同的是它是由被调用者将参数从栈中清除的.
可变参数............
猜测也在Windows API函数调用约定中吧.基于约定的东西....
另外在delphi中根本就没有可变参数,但是一样能与c/c++写的可变参数函数传递数据,
用的是:(抄一段)
function   WriteLog(s:PChar):integer;stdcall;varargs;external   'MYDLL.dll';
可见一斑呀...............
oldrev 2007-08-24
D没有明确支持C++ ABI,感觉用这个不太靠谱。

这个类是不是 COM 接口?
player7 2007-08-24
现在的问题,现在到底是谁在清栈呀?
按规定应该是C++那边在清栈吧,可是它怎么知道是几个参数呢?
player7 2007-08-24
我不太懂呀,全部是纯虚函数,应该算是模仿COM的吧?
achun 2007-08-24
没有那么复杂吧.看看这个
http://www.pconline.com.cn/pcedu/empolder/gj/c/0411/484715.html
因为他的第一个参数是format,所有正好可以通过解析获取可变参数的类型.换句话说其实第一个参数中已经包含了其他参数的信息了.
理论上这中调用仍然是不可靠的.好像那本数上说过记不清了.
虚函数和参数传递没有关系呀.
achun 2007-08-24
从这一点上也可以看出,我们写的所有函数间的参数传递,
实际上运行期并没有什么安全的检查,都是约定式的.
要说有检查那也是编译期的.
oldrev 2007-08-24
Windows调用约定 __stdcall 是不支持可变参数的,只有 C调用约定 __cdecl 才支持。
player7 2007-08-24
是的,所有现在我搞不清了,
virtual void __STDCALL System_Log(const char *format, ...) = 0;


到底是哪一种调用? 为什么它能通过编译器检查?
player7 2007-08-24
我想了一下,是不是这样的:

正常的可变参数用cdecl,调用者清栈,被调用者只管使用参数即可;这样从编译器里保证了清栈的正确性.

而stdcall是由被调用者清栈,他根据的是 format字符串参数来清栈,这样,必须人工的保证字符串中" %"的个数与可变参数的个数相匹配,否则就会出错.

所以,D语言用 Windows协议就可以正常工作,因为调用方不用任何责任;
但是,安全性太低了.
Global site tag (gtag.js) - Google Analytics