?c++ 调用DLL函数,出现错误

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call. This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

错误原因:

你定义函数指针原型时出错。

其实你定义的没有错,但是编译器不认识而已,因为你调用的dll函数是一个远函数,而且是一个C函数,你得告诉编译器它是个c函数才行。那么你就可以在定义该函数的时候加上一句话,

FAR PASCAL 或者 __stdcall 这个就OK了。

具体做法:

比如说你要定义一个 返回类型为空,参数为空的函数指针:

typedef void (*LPFUN)(void);

这样确实跟我们dll里的函数匹配了,上面也说了,我们应该添上几个字,告诉编译器这个是一个远的C函数。

typedef void (WINAPI *LPFUN)(void);

typedef void (__stdcall *LPFUN)(void);

typedef void    (FAR PASCAL *LPFUN)    (void);

像上面这样定义就OK了,如果用的是VC++,那么直接用第一种定义就ok了。

注意,上面是使用 MFC (DLL)的做法。

如果是WIN32 DLL,得相应的去掉WINAPI ,__stdcall ,FAR PASCAL 这几个参数。因为WIN32 DLL 默认的入栈方式为 __cedcall方式,不是__stdcall方式。

具体的组合方式太多了,反正知道错误的原因是声明相应的函数未匹配就行了。

调用DLL里的函数 或 类成员函数 碰到此错误:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

函数定义的调用规则,和实际的调用规则不同。如 编译器默认的是__cdecl,而__stdcall 类型的函数却用了 __cdecl 的调用规则,由于编译时不会报错,结果出现了运行时异常。

所以把在函数定义中进行设置调用规则即可解决此问题。

如:  typedef void (__stdcall Foo)(int a);

很久没写代码,一天几行的代码:

typedef  int ( *PFUN)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
void CTestProcessMonitorDlg::OnBnClickedButton1()
{
    // TODO: Add your control notification handler code here

//MessageBox(TEXT("Hello"), TEXT("Test"));

//typedef void (*pfv) ();

HMODULE hmod = ::LoadLibraryExW(TEXT("user32.dll"), NULL, 0);
    if (hmod != NULL)
    {
        PFUN pFun= (PFUN)GetProcAddress(hmod, "MessageBoxW");
        if (pFun != NULL)
        {
            pFun(m_hWnd, TEXT("Hello"), TEXT("Test"), MB_YESNO);
        }

:FreeLibrary(hmod);
    }

}

突然出现以下的错误:

Run-Time Check Failure #0 - The value of ESP was not properly saved across a function call.  This is usually a result of calling a function declared with one calling convention with a function pointer declared with a different calling convention.

代码改为如下, 则问题没有了

typedef  int (WINAPI *PFUN)(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption, UINT uType);
void CTestProcessMonitorDlg::OnBnClickedButton1()
{
    // TODO: Add your control notification handler code here

//MessageBox(TEXT("Hello"), TEXT("Test"));

//typedef void (*pfv) ();

HMODULE hmod = ::LoadLibraryExW(TEXT("user32.dll"), NULL, 0);
    if (hmod != NULL)
    {
        PFUN pFun= (PFUN)GetProcAddress(hmod, "MessageBoxW");
        if (pFun != NULL)
        {
            pFun(m_hWnd, TEXT("Hello"), TEXT("Test"), MB_YESNO);
        }

::FreeLibrary(hmod);
    }
                      
}

时间: 2024-08-05 02:54:00

?c++ 调用DLL函数,出现错误的相关文章

动态调用DLL函数有时正常,有时报Access violation的异常

动态调用DLL函数有时正常,有时报Access violation的异常 typedef int (add *)(int a,int b); void test() { hInst=LoadLibraryA("aimdtl.dll"); (FARPROC &)add=GetProcAddress(hInst,"add"); add(1,2); } 按这个代码执行,add函数有时OK,有时报Access violation的异常.看到提示,第一反应就是内存异常

delphi 基础之三 编写和调用dll文件

delphi 编写和调用dll文件   Windows 的执行文件可以划分为两种形式程序和动态连接库 (DLLs).一般程序运行是用.EXE文件,但应用程序有时也可以调用存储在DLL的函数. 在如下几种情况下,调用DLL 是合理的: 1) 不同的程序使用相同的DLL ,这样只需要将DLL 在内存中装载一次,节省了内存的开销. 2) 当某些内容需要升级的时候,如果使用DLL 只需要改变DLL 就可以了,而不需要把整个程序都进行变动. 3) 由于DLL 是独立于语言的,所以,当不同语言习惯的人共同开

C# 互操作性入门系列(二):使用平台调用调用Win32 函数

好文章搬用工模式启动ing ..... { 文章中已经包含了原文链接 就不再次粘贴了 言明 改文章是一个系列,但只收录了2篇,原因是 够用了 } --------------------------------------------------------------------------------------- C#互操作系列文章: C#互操作性入门系列(一):C#中互操作性介绍 C#互操作性入门系列(二):使用平台调用调用Win32 函数 C#互操作性入门系列(三):平台调用中的数据封

LabVIEW如何方便地调用DLL文件

转自:http://bbs.elecfans.com/jishu_469502_1_1.html LabVIEW调用DLL文件 LabVIEW支持通过调用DLL文件的方式与其它编程语言混合使用.比如,在实际的工程项目中,用户可以用C++语言实现软件的运算部分,并把这些功能构建在DLL文件中,然后再使用 LabVIEW编写程序的界面部分,并通过调用编写好的DLL来调用运算部分的功能. LabVIEW 中是通过Call Library Function Node(CLN)节点来完成DLL文件调用的.

在VS2012中采用C++中调用DLL中的函数 (4)

这两天因为需要用到VS2012来生成一个DLL代码,但是之前并没有用过DLL相关的内容,从昨天开始尝试调试DLL的文件调用,起初笔者在网络上找到了3片采用VSXXX版本进行调试的例子,相关的内容见本人Blog在C++中调用DLL中的函数(1)(2)(3) 但是问题出现了,上面讲述的步骤很详细但是在自己运行的时候却会出现错误,于是今天在使用google“vs2012 c++调用dll”时,发现了一篇MSDN上的指南:http://msdn.microsoft.com/zh-cn/library/m

在C++中调用DLL中的函数(2)

转自:http://blog.sina.com.cn/s/blog_53004b4901009h3b.html 应用程序使用DLL可以采用两种方式: 一种是隐式链接,另一种是显式链接.在使用DLL之前首先要知道DLL中函数的结构信息. Visual C++6.0在VC\bin目录下提供了一个名为Dumpbin.exe的小程序,用它可以查看DLL文件中的函数结构.另外,Windows系统将遵循下面的搜索顺序来定位DLL: 1.包含EXE文件的目录, 2.进程的当前工作目录, 3.Windows系统

在VS2012中采用C++中调用DLL中的函数(4)

转自:http://www.cnblogs.com/woshitianma/p/3683495.html 这两天因为需要用到VS2012来生成一个DLL代码,但是之前并没有用过DLL相关的内容,从昨天开始尝试调试DLL的文件调用,起初笔者在网络上找到了3片采用VSXXX版本进行调试的例子,相关的内容见本人Blog在C++中调用DLL中的函数(1)(2)(3) 但是问题出现了,上面讲述的步骤很详细但是在自己运行的时候却会出现错误,于是今天在使用google"vs2012 c++调用dll"

IronPython调用C# DLL函数方法

C# DLL源码 using System; using System.Collections.Generic; using System.Text; using System.Security.Cryptography; namespace Common { public class SimpleHash { public string HashCalc(byte[] audioBuffer, byte[] key) { ...... return result; } } } 需要在IronP

C语NET调用 C++ dll 函数 时传递字符串 需要注意的问题

1:C# 调用 返回 字符串 C++ native dll 函数 的注意事项: a:C++ DLL的返回值,安全的做法是分配一个全局 char 数组,把要返回的 char * 复制到这个 char 数组中, 1 char buff[255]; 2 3 const char* __stdcall ReturnString() 4 { 5 strcpy(buff,"xxxxxxxxxxxxxxx"); 6 return buff; 7 } b:C# 收到 字符串后,需要 Marshal 1