В 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, как и другой неуправляемый код валится при не соответствии соглашений о вызове.
Спасибо.
VB.NET 2003 __stdcall or __cdecl
Правила форума
Пожалуйста, ознакомьтесь с правилами данного форума
Пожалуйста, ознакомьтесь с правилами данного форума
-
- Маньяк
- Сообщения: 2803
- Зарегистрирован: 29 май 2003, 22:29
- Откуда: Магадан - Миссиссага
- Ильгиз
- Пользователь
- Сообщения: 55
- Зарегистрирован: 13 сен 2005, 12:00
- Откуда: Уфа - Китченер
Мне кажется, что информация о соглашении вызова, несмотря на очевидную полезность, в библиотеке будет отсутствовать во имя уменьшения необходимых циклов процессора. Это только моя гипотеза. Я почти ничего не знаю о DLL.
Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево). Только "cdecl" предполагает, что вызыватель освободит стек от параметров после того, как функция вернулась, а "stdcall" — что это проделает вызываемая функция перед возвратом.
(Мне кажется, что в случае "stdcall" функция не может объявить получение произвольного количества параметров, так как компилятор не сможет сгенерировать код очистки стека. Похожая проблема существует с соглашением "pascal" передачи параметров, слева направо).
В случае вызова двух функций, скомпилированных для разных соглашений "cdecl" и "stdcall", кодом, подразумевающим только одно из этих соглашений, вызовы сработают, но стек останется в неожиданном состоянии. И если вызывающий код подразумевал соглашение "stdcall", то вероятность, что после этого произойдёт крах, даже меньше.
И вот ещё, что я нагуглил:
Возможно, есть и каноническая документация от Микрософта на этот счёт, просто я не искал.
Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево). Только "cdecl" предполагает, что вызыватель освободит стек от параметров после того, как функция вернулась, а "stdcall" — что это проделает вызываемая функция перед возвратом.
GCC 4 Manual, Function Attributescdecl
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.
(Мне кажется, что в случае "stdcall" функция не может объявить получение произвольного количества параметров, так как компилятор не сможет сгенерировать код очистки стека. Похожая проблема существует с соглашением "pascal" передачи параметров, слева направо).
В случае вызова двух функций, скомпилированных для разных соглашений "cdecl" и "stdcall", кодом, подразумевающим только одно из этих соглашений, вызовы сработают, но стек останется в неожиданном состоянии. И если вызывающий код подразумевал соглашение "stdcall", то вероятность, что после этого произойдёт крах, даже меньше.
И вот ещё, что я нагуглил:
Programming with DAQmx Base in VB 6.0, VB.NET and C#.C# and Visual Basic.NET by default call C DLL functions using the stdcall calling convention
Возможно, есть и каноническая документация от Микрософта на этот счёт, просто я не искал.
-
- Маньяк
- Сообщения: 2803
- Зарегистрирован: 29 май 2003, 22:29
- Откуда: Магадан - Миссиссага
Спасибо, Ильгиз, за мнение.
#define PASCAL __stdcall
Имхо, конечно.
Да, отсутствует.Ильгиз писал(а):Мне кажется, что информация о соглашении вызова, несмотря на очевидную полезность, в библиотеке будет отсутствовать...
В разных.Ильгиз писал(а):Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево).
Верно. Используют в этом случае cdeclИльгиз писал(а): (Мне кажется, что в случае "stdcall" функция не может объявить получение произвольного количества параметров ....
Конечно. См., например, <windef.h>Ильгиз писал(а): Похожая проблема существует с соглашением "pascal" передачи параметров, слева направо).
#define PASCAL __stdcall
Приложения с неуправляемым кодом всегда крэш при несовпадении соглашений о вызове функций DLL. Только если параметров нет, то может и повезёт.Ильгиз писал(а): В случае вызова двух функций, скомпилированных для разных соглашений "cdecl" и "stdcall", кодом, подразумевающим только одно из этих соглашений, вызовы сработают, но стек останется в неожиданном состоянии. И если вызывающий код подразумевал соглашение "stdcall", то вероятность, что после этого произойдёт крах, даже меньше.

- Ильгиз
- Пользователь
- Сообщения: 55
- Зарегистрирован: 13 сен 2005, 12:00
- Откуда: Уфа - Китченер
Ссылка на документацию?vg писал(а):В разных.Ильгиз писал(а):Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево).
Вот ещё один противоположный аргумент:

Delphi 5 Guide, Procedures and Functions
Согласно Борланду и ФСФ, это определение только верно для способа очистки стека, но не для порядка передачи параметров.См., например, <windef.h>
#define PASCAL __stdcall
Здесь я ничего не могу сказать, потому что ничего не знаю.Приложения с неуправляемым кодом всегда крэш при несовпадении соглашений о вызове функций DLL. Только если параметров нет, то может и повезёт.Имхо, конечно.
-
- Маньяк
- Сообщения: 2803
- Зарегистрирован: 29 май 2003, 22:29
- Откуда: Магадан - Миссиссага
Я протупил. Ты прав.Ильгиз писал(а):Ссылка на документацию?vg писал(а):В разных.Ильгиз писал(а):Возможно, что "cdecl" и "stdcall" передают параметры в одном и том же порядке (справа налево).
http://msdn.microsoft.com/library/defau ... ntions.asp