,和后面的原型,比如: ;hello32.asm .386 .model flat MessageBoxA proto stdcall hwnd:dword, text:dword, caption :dword, buttons:dword ExitProcess proto stdcall exitcode:dword ;实际上这里的原型有的可以随意填,有的却必须保持一致,大概有overload proto stdcall void:dword InitializeCriticalSection proto stdcall void:dword EnterCriticalSection proto stdcall void:dword LeaveCriticalSection proto stdcall void:dword GetSystemInfo proto stdcall void:dword GetProcAddress proto stdcall handle:dword,procname:dword GetCurrentProcess proto stdcall .data
RemoteThreadProc(LPVOID lpParam) { PDATA pData = (PDATA)lpParam; //定义API函数原型 HMODULE (__stdcall *MyLoadLibrary)(LPCTSTR); FARPROC (__stdcall *MyGetProcAddress)(HMODULE, LPCSTR); HMODULE (_ _stdcall *MyGetModuleHandle)(LPCTSTR); int (__stdcall *MyMessageBox)(HWND, LPCTSTR, LPCTSTR, UINT ); DWORD (__stdcall *MyGetModuleFileName)(HMODULE, LPTSTR, DWORD); //对各函数地址进行赋值 MyLoadLibrary = (HMODULE (__stdcall *)(LPCTSTR))pData->dwLoadLibrary; MyGetProcAddress = (FARPROC (__stdcall *
'; function DeleteObject(p1: Longword): BOOL; external 'DeleteObject@gdi32.dll stdcall'; function GetPM(nIndex:Integer):Integer; external 'GetSystemMetrics@user32.dll stdcall'; //botva2 function ImgLoad gdipShutdown; external 'gdipShutdown@{tmp}\botva2.dll stdcall delayload'; function WrapBtnCallback delayload'; procedure BtnSetFont(h:HWND; Font:Cardinal); external 'BtnSetFont@{tmp}\botva2.dll stdcall delayload'; function BtnGetChecked(h:HWND):boolean; external 'BtnGetChecked@{tmp}\botva2.dll stdcall
'; function KeUnstackDetachProcess(ApcState: PKAPC_STATE): NTSTATUS; stdcall; external NtKernel name '_KeUnstackDetachProcess'; function PsGetProcessImageFileName(Process: PVOID): PUCHAR; stdcall; external NtKernel name '_PsGetProcessImageFileName'; function KeGetCurrentThread(): PKThread; stdcall; external name '_PsGetCurrentThread'; function PsGetCurrentProcessId(): HANDLE; stdcall; external NtKernel name '_PsGetCurrentProcessId'; procedure ObDereferenceObject(MyObject: PVOID); stdcall; external NtKernel
解决函数名由于不同编译器造成的名字匹配问题 // 通常c++编译器编译时会对函数进行改名,而c编译器不会 // _declspec(dllexport)说明该函数为导出函数 /* 如果函数用"_stdcall "进行修饰,在动态引用的时候,要对"函数指针"也要进行"_stdcall"修饰 __stdcall:Windows API默认的函数调用协议 extern "C" _declspec(dllexport ) double _stdcall qAdd(double a, double b); extern "C" _declspec(dllexport) double _stdcall qSub(double " 修饰 //typedef double(_stdcall *ADDPROC)(double, double); //typedef double(_stdcall *SUBPROC) *ADDPROC)(double, double); //typedef double(_stdcall *SUBPROC)(double, double); typedef
标准调用约定(stdcall) 标准调用约定的“标准”是由微软为自己的调用约定所起的名称stdcall得来。 stdcall规定: 调用方将所需参数放入栈中 参数放入顺序为从右往左 调用结束后由被调用方清楚参数 要求被调用方从栈中删除参数的特点: 被调用方要完成清除参数的任务,必须清楚的知道栈中有多少个参数,只有在函数参数数量固定不变时才有可能 因此,类似printf这种可变参数的函数无法使用stdcall。 stdcall的优点: 在每次函数调用之后,不需要通过代码从栈中清除参数,因而能够生成体积稍小、速度稍快的程序。 微软对所有共享库(DLL)文件输出的参数数量固定的函数使用stdcall约定。 x86 fastcall调用约定 fastcall调用约定时stdcall约定的一个变体。 fastcall规定: 能够将最多两个参数存放在寄存器中 传递给函数的前两个参数将分别位于ECX和EDX寄存器中 剩余参数以类似于stdcall约定的方式从右往左放入栈上 C++调用约定(thiscall
// 创建一个libvlc实例,它是引用计数的 2 [DllImport("libvlc", CallingConvention = CallingConvention.StdCall 5 6 // 释放libvlc实例 7 [DllImport("libvlc", CallingConvention = CallingConvention.StdCall (IntPtr libvlc_instance); 10 11 [DllImport("libvlc", CallingConvention = CallingConvention.StdCall 从视频来源(例如Url)构建一个libvlc_meida 16 [DllImport("libvlc", CallingConvention = CallingConvention.StdCall / 创建libvlc_media_player(播放核心) 30 [DllImport("libvlc", CallingConvention = CallingConvention.StdCall
msg) {cout << msg << endl ;} //Interface interface IX : IUnknown { virtual void __stdcall Fx() = 0; }; interface IY : IUnknown { virtual void __stdcall Fy() = 0; }; interface IZ : IUnknown { virtual void __stdcall Fz() = 0; }; //Forward references for GUIDs QueryInterface(const IID& iid, void** ppv); virtual ULONG __stdcall AddRef() { return virtual void __stdcall Fy() {cout << “Fy” << endl ;} }; HRESULT __stdcall CA::QueryInterface
#define JNIEXPORT __declspec(dllexport) #define JNIIMPORT __declspec(dllimport) #define JNICALL __stdcall JNICALL宏定义作用 : ① Windows JNICALL : JNICALL 被定义为 __stdcall , __stdcall 是一种函数调用参数的约定 , 在 Windows 中调用函数时 , 该函数的参数是以 栈 的形式保存的 , 栈 中元素是后进先出的 , __stdcall 表示参数是从右到左保存的 ; __stdcall 用于 定义 函数入栈规则 ( 从右到左 ) , 和 堆栈清理规则 " , 在编译时 , 使用 " __stdcall " 代替 JNICALL ; 2 . jobject instance, jint i, jstring s_) { } ② 编译过程中宏替换后的代码 : extern "C" __declspec(dllexport) void __stdcall
nFormat); int __stdcall zplay_Play(ZPLAY_HANDLE handle); int __stdcall zplay_Pause(ZPLAY_HANDLE handle ); int __stdcall zplay_Stop(ZPLAY_HANDLE handle); void __stdcall zplay_GetPosition(ZPLAY_HANDLE handle __stdcall zplay_Close(ZPLAY_HANDLE handle); int __stdcall zplay_DestroyZPlay(ZPLAY_HANDLE handle); 3 和zplay_OpenFile的函数指针: typedef ZPLAY_HANDLE (_stdcall* pfnCreateZPlay)(); typedef int (_stdcall* pfnOpenFile * pfnCreateZPlay)(); typedef int (_stdcall* pfnOpenFile)(ZPLAY_HANDLE handle, const char* sFileName,
IZ:IUnknown { virtual void _stdcall Fz() = 0 ; }; // forward references for guids QueryInterface( const IID & iid, void ** ppv); virtual ULONG _stdcall AddRef(){ virtual void _stdcall Fx() {cout << “ FX “ << endl;MessageBox(NULL, “ hello world “ , “ caption “ ,MB_OK);}; // interface IY implementation virtual void _stdcall Fy(){cout << “ FY “ << endl;} }; HRESULT _stdcall CA::QueryInterface( const IID & iid,
STDCALL 调用约定规定由被调用者负责将堆栈平衡清除。 STDCALL与CDECL只在参数平衡上有所不同,其余部分都一样,但该约定不定参数函数无法使用。 通过以上分析发现_cdecl与_stdcall两者只在参数平衡上有所不同,其余部分都一样,但经过优化后_cdecl调用方式的函数在同一作用域内多次使用,会在效率上比_stdcall髙,这是因为_cdecl 此外,函数使用堆栈来传递其他参数,并在返回之前使用类似于STDCALL约定的方式来平衡堆栈。 #include <iostream> void __stdcall Show(int x, int y) { printf("%d --> %d \n",x,y); } int __stdcall
福哥答案2020-09-04: 初级回答: stdcall和cdecl两者的参数传递顺序都是从右向左。 不同点是stdcall在被调用函数 (Callee) 返回前,由被调用函数 (Callee) 调整堆栈。 __fastcall和__stdcall很象,唯一差别就是头两个参数通过寄存器传送。 3) 函数名修改规则同stdcall。 返回方式同__stdcall. 5.__nakedcall 这是一个很少见的调用约定,一般程序设计者建议不要使用。
type TNewMessageBoxA = function (_hWnd: HWND; lpText, lpCaption: PAnsiChar; uType: UINT): Integer; stdcall ; type TNewMessageBeep = function (uType: UINT): BOOL; stdcall; begin Result := True; end; / function NewOpenProcess(dwDesiredAccess: DWORD; bInheritHandle: BOOL; dwProcessId: DWORD): THandle; stdcall hhk := SetWindowsHookEx(WH_CALLWNDPROC, HookProc, hInstance, 0); end; //结束HOOK procedure EndHook; stdcall ; external 'hookdll.dll'; procedure EndHook; stdcall; external 'hookdll.dll'; implementation {$R *
declspec(dllexport) 5 #else 6 #define DLL_DEMO extern "C" __declspec(dllimport) 7 #endif 8 DLL_DEMO int __stdcall Add(int a, int b); 9 #endif 源文件: 1 #define DLLDEMO_EXPORTS 2 #include "dll_demo.h" 3 4 int __stdcall Add(int a, int b) 5 { 6 return (a + b); 7 } def文件: 1 LIBRARY 2 EXPORTS 3 Add @ 1 函数需要声明为 stdcall 调用方式才能被易语言调用,def文件的主要作用为解决使用stdcall方式后函数名被改变的问题。
C语言中的函数默认是__cdecl调用,C++中可用__stdcall来显示声明调用,但也可以用extern “C” 用python调用dll时需要根据不同的调用约定而使用不同的函数。 dll源文件: [cpp] view plaincopy #include <iostream> extern "C" _declspec(dllexport) int __stdcall stdAdd(int a, int b) { std::cout << "This is __stdcall dll" << std::endl; return a + b; 总结:如果dll是stdcall调用,则python中用windll加载,如果dll是cdecl调用,则python用cdll加载。 注*以上是在python3.3中运行的
问题描述: 在外部组件CB聚合内部组件CA时,内部组件的非委托未知接口示意如下: struct INondelegatingUnknown { virtual HRESULT __stdcall NondelegatingQueryInterface(const IID&, void**) = 0; virtual ULONG __stdcall NondelegatingAddRef QueryInterface(); virtual ULONG __stdcall AddRef(); virtual ULONG __stdcall Release(); virtual HRESULT __stdcall NondelegatingQueryInterface(const IID&, void**); virtual ULONG __stdcall QueryInterface() = 0; virtual ULONG __stdcall AddRef() = 0; virtual ULONG __stdcall Release(
解决函数名由于不同编译器造成的名字匹配问题 // 通常c++编译器编译时会对函数进行改名,而c编译器不会 // _declspec(dllexport)说明该函数为导出函数 /* 如果函数用"_stdcall "进行修饰,在动态引用的时候,要对"函数指针"也要进行"_stdcall"修饰 __stdcall:Windows API默认的函数调用协议 extern "C" _declspec(dllexport ) double _stdcall qAdd(double a, double b); extern "C" _declspec(dllexport) double _stdcall qSub(double extern “C” 解决函数名由于不同编译器造成的名字匹配问题 通常C++编译器编译时会对函数进行改名,而C编译器不会 _declspec(dllexport)说明该函数为导出函数 如果函数用_stdcall 进行修饰,在动态引用的时候,要对函数指针也要进行_stdcall修饰 Next计划 [C-C++]DLL之旅2 : 调用DLL(静态&动态加载)
__cdecl、__stdcall、__fastcall是C/C++里中经常见到的三种函数调用方式。 其中__cdecl是C/C++默认的调用方式,__stdcall是windows API函数的调用方式,只不过我们在头文件里查看这些API的声明的时候是用了WINAPI的宏进行代替了,而这个宏其实就是_ _stdcall了。 __stdcall: windows API默认方式,参数从右向左入栈,被调函数负责栈平衡。 __fastcall: 快速调用方式。 上图我们看到了__cdecl中由主调函数完成了,那么__stdcall呢,在被调函数Fun3()中,转向被调函数结尾处的代码,我们看到了这一句: ? 那么Fun1()结尾处又是如何呢? ?
STDCALL与CDECL只在参数平衡上有所不同,其余部分都一样,但该约定不定参数函数无法使用。 通过以上分析发现_cdecl与_stdcall两者只在参数平衡上有所不同,其余部分都一样,但经过优化后_cdecl调用方式的函数在同一作用域内多次使用,会在效率上比_stdcall髙,这是因为_cdecl 可以使用复写传播优化,而_stdcall的平栈都是在函数内部完成的,无法使用复写传播这种优化方式。 此外,函数使用堆栈来传递其他参数,并在返回之前使用类似于STDCALL约定的方式来平衡堆栈。 #include <iostream>void __stdcall Show(int x, int y){ printf("%d --> %d \n",x,y);}int __stdcall ShowPrint