Легенда:
новое сообщение
закрытая нитка
новое сообщение
в закрытой нитке
старое сообщение
|
- Напоминаю, что масса вопросов по функционированию форума снимается после прочтения его описания.
- Новичкам также крайне полезно ознакомиться с данным документом.
[C++] __stdcall or __cdecl 17.10.05 03:32
Автор: void <Grebnev Valery> Статус: Elderman
|
Можно ли програмно определить, с какими соглашениями экспортируемых функций изготовлена DLL?
Типа есть DLL. Надо определить какие соглашения о вызовах были использованы для экспортируемых функций при её компиляции.
Спасибо.
|
 |
[C++] В общем случае нельзя 17.10.05 10:55
Автор: amirul <Serge> Статус: The Elderman
|
> Типа есть DLL. Надо определить какие соглашения о вызовах > были использованы для экспортируемых функций при её > компиляции.
Но можно попробовать эвристик. Найти выход из функции, если перед выходом со стека снимается не только фрейм, но и аргументы - то 100% __stdcall:
mov esp, ebp
pop ebp
retn N
---
Если же перед выходом аргументы не снимаются, то либо __cdecl, либо __stdcall без параметров:
mov esp, ebp
pop ebp
ret
---
Это если функцию вызывать нельзя. Если же такого ограничения нет, то перед вызовом (перед выкладыванием аргументов) сохраняешь старое значение указателя стека, вызываешь, проверяешь были ли сняты аргументы. Если были - __stdcall, если нет - __cdecl.
|
 |  |
[Net] NET как-то по-другому работает со стеком. Не помню где читал, но там другая модель стека. 18.10.05 04:21
Автор: void <Grebnev Valery> Статус: Elderman
|
Спасибо за ответ. Вот ещё вопрос.
В 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, как и другой неуправляемый код валится при не соответствии соглашений о вызове.
Спасибо.
|
 |  |  |
дотнет тут нипричем 21.10.05 16:23
Автор: z0 <z0> Статус: Member
|
> Вопрос - почему обе функции вызываются нормально? Как .NET > определяет соглашение о вызовах? Обычный VB 6.0, как и > другой неуправляемый код валится при не соответствии > соглашений о вызове. > > Спасибо.
есть такая штука - декорация имен, это ее работа
|
 |  |  |  |
Декроирование здесь нипричём. 22.10.05 21:40
Автор: void <Grebnev Valery> Статус: Elderman
|
> > Вопрос - почему обе функции вызываются нормально? Как > .NET > > определяет соглашение о вызовах? Обычный VB 6.0, как и > > другой неуправляемый код валится при не соответствии > > соглашений о вызове. > > > > Спасибо. > > есть такая штука - декорация имен, это ее работа Декроирование здесь нипричём.
В DLLs (dumpbin /EXPORTS ....) имена не декорированы (я прописывал сам в def файле )
|
 |  |  |  |  |
да действительно 25.10.05 14:47
Автор: z0 <z0> Статус: Member
|
да действительно
к моему собственному (и моего софтайса) удивлению оказалось
что CLR-runtime имеет код для вызова внешних функций типа
mov [loc_esp],esp
push [param_2]
push [param_1]
call [loc_entry]
... bla bla bla
mov esp,[loc_esp]
то есть благодаря тому что __stdcall и __cdecl отличаются только retn/retn X
то такому коду абсолютно монопенисуально что одно что другое
так что все равно что писАть (C#):
[DllImport("lib1.dll", CallingConvention=CallingConvention.StdCall)]
public static extern String proc1(int param1, int param2);
или
[DllImport("lib1.dll", CallingConvention=CallingConvention.Cdecl)]
public static extern String proc1(int param1, int param2);
результат одинаков (для данной реализации mscorwks.dll, конкретно FW 1.1)
так что признаю - был неправ
|
 |  |  |  |  |  |
Спасибо за анализ. 27.10.05 01:30
Автор: void <Grebnev Valery> Статус: Elderman
|
Спасибо за анализ.
> mov [loc_esp],esp > push [param_2] > push [param_1] > call [loc_entry] > ... bla bla bla > mov esp,[loc_esp] > > то есть благодаря тому что __stdcall и __cdecl отличаются > только retn/retn X > то такому коду абсолютно монопенисуально что одно что > другое > так что все равно что писАть (C#): > [DllImport("lib1.dll", > CallingConvention=CallingConvention.StdCall)] > public static extern String proc1(int param1, int param2); > или > [DllImport("lib1.dll", > CallingConvention=CallingConvention.Cdecl)] > public static extern String proc1(int param1, int param2); > результат одинаков (для данной реализации mscorwks.dll, > конкретно FW 1.1)
|
|
|