Страница 1 из 1

VB.NET 2003 __stdcall or __cdecl

Добавлено: 17 окт 2005, 17:16
vg
В VB.NET 2003 я объявил две одинаковые процедуры.

Declare Sub cdecl_Test Lib "cdeclmpilib.dll" (ByVal V1 As Double, ByVal V2 As Double)

Declare Sub std_Test Lib "stdmpilib.dll" (ByVal V1 As Double, ByVal V2 As Double)


Первая функция -
extern "C" __declspec(dllexport) void __stdcall std_Test( double v1, double v2 )
{
if ( hlib )
{
TCHAR s[512];

_stprintf( s, _T("v1 = %f v2 = %f"), v1, v2 );

MessageBox(NULL, s, "Test", MB_OK );
}
}
Вторая функция - такая же, только вместо __stdcall декларировано __cdecl соглашение

extern "C" __declspec(dllexport) void __cdecl cdecl_Test( double v1, double v2 )

Вопрос - почему обе функции вызываются нормально? Как .NET определяет соглашение о вызовах? Обычный VB 6.0, как и другой неуправляемый код валится при не соответствии соглашений о вызове.

Спасибо.

Добавлено: 17 окт 2005, 22:05
Ильгиз
Мне кажется, что информация о соглашении вызова, несмотря на очевидную полезность, в библиотеке будет отсутствовать во имя уменьшения необходимых циклов процессора. Это только моя гипотеза. Я почти ничего не знаю о DLL.

Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево). Только "cdecl" предполагает, что вызыватель освободит стек от параметров после того, как функция вернулась, а "stdcall" — что это проделает вызываемая функция перед возвратом.
cdecl
On the Intel 386, the cdecl attribute causes the compiler to assume that the calling function will pop off the stack space used to pass arguments. This is useful to override the effects of the -mrtd switch.

stdcall
On the Intel 386, the stdcall attribute causes the compiler to assume that the called function will pop off the stack space used to pass arguments, unless it takes a variable number of arguments.
GCC 4 Manual, Function Attributes

(Мне кажется, что в случае "stdcall" функция не может объявить получение произвольного количества параметров, так как компилятор не сможет сгенерировать код очистки стека. Похожая проблема существует с соглашением "pascal" передачи параметров, слева направо).

В случае вызова двух функций, скомпилированных для разных соглашений "cdecl" и "stdcall", кодом, подразумевающим только одно из этих соглашений, вызовы сработают, но стек останется в неожиданном состоянии. И если вызывающий код подразумевал соглашение "stdcall", то вероятность, что после этого произойдёт крах, даже меньше.

И вот ещё, что я нагуглил:
C# and Visual Basic.NET by default call C DLL functions using the stdcall calling convention
Programming with DAQmx Base in VB 6.0, VB.NET and C#.

Возможно, есть и каноническая документация от Микрософта на этот счёт, просто я не искал.

Добавлено: 18 окт 2005, 18:03
vg
Спасибо, Ильгиз, за мнение.
Ильгиз писал(а):Мне кажется, что информация о соглашении вызова, несмотря на очевидную полезность, в библиотеке будет отсутствовать...
Да, отсутствует.
Ильгиз писал(а):Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево).
В разных.
Ильгиз писал(а): (Мне кажется, что в случае "stdcall" функция не может объявить получение произвольного количества параметров ....
Верно. Используют в этом случае cdecl
Ильгиз писал(а): Похожая проблема существует с соглашением "pascal" передачи параметров, слева направо).
Конечно. См., например, <windef.h>
#define PASCAL __stdcall
Ильгиз писал(а): В случае вызова двух функций, скомпилированных для разных соглашений "cdecl" и "stdcall", кодом, подразумевающим только одно из этих соглашений, вызовы сработают, но стек останется в неожиданном состоянии. И если вызывающий код подразумевал соглашение "stdcall", то вероятность, что после этого произойдёт крах, даже меньше.
Приложения с неуправляемым кодом всегда крэш при несовпадении соглашений о вызове функций DLL. Только если параметров нет, то может и повезёт. :lol: Имхо, конечно.

Добавлено: 18 окт 2005, 19:58
Ильгиз
vg писал(а):
Ильгиз писал(а):Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево).
В разных.
Ссылка на документацию?

Вот ещё один противоположный аргумент:
Изображение
Delphi 5 Guide, Procedures and Functions
См., например, <windef.h>
#define PASCAL __stdcall
Согласно Борланду и ФСФ, это определение только верно для способа очистки стека, но не для порядка передачи параметров.
Приложения с неуправляемым кодом всегда крэш при несовпадении соглашений о вызове функций DLL. Только если параметров нет, то может и повезёт. :lol: Имхо, конечно.
Здесь я ничего не могу сказать, потому что ничего не знаю.

Добавлено: 18 окт 2005, 22:09
vg
Ильгиз писал(а):
vg писал(а):
Ильгиз писал(а):Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево).
В разных.
Ссылка на документацию?
Я протупил. Ты прав.
http://msdn.microsoft.com/library/defau ... ntions.asp