• vb调用vcdll


    近日开发一个程序,用到动态链接库,在VB中调用时遇到了一些问题。我查了一些资料,也看了一下CSDN上的文章,感觉这些文章对在VB中调用VC++开发的DLL这一问题阐述得不够详细。因此在我的问题得到解决之余,特为初接触DLL的朋友们写下这篇文章。
       
    本文中关于调用约定的解决方法,也适用于解决其它编程语言之间
    DLL调用的兼容问题。

    关于DLL的创建与调用
      使用VC++的向导即可。具体操作如下:打开菜单“File\New”→选择“Projects\Win32 Dynamic-Link Library”→选择“A simple DLL project”即可。这时系统会自动生成3个文件:*.cppstdafx.cppstdafx.h
      之后将入口函数
    DLLMain()补充完整,再添加你自定义的函数的代码。如果你自定义的函数很多,可以将这些函数的声明部分统一写入一个头文件中。再在.cpp文件首部用“#include”语句引入这个头文件。注意函数声明前要加上“__declspec(dllexport)”。
      (如果你建
    DLL时选择的是第三种类型(加入示例代码),则在函数声明及定义前都要加上系统定义的宏“*_API”。)
      在
    VB中用如下语句声明:“Declare Function 函数名 Lib "完整路径\文件名.dll" [Alias "函数别名"] (ByVal 变量1 As 类型1, ByVal 变量2 As 类型2,) As 类型3,与调用API函数类似。
      注意:若在窗体代码的“通用”部分使用,“
    Declare”前要加“Private”;若在Moudle中使用,“Declare”前要加“Public”。若将DLL文件放在系统目录(“\Windows\System”或“\WinNT\System32”)或程序可执行文件所在目录下,“Lib”后只写出DLL主文件名即可。
      具体的实例代码见④(修正后的,可直接运行)。 

    关于入口点
      如上编写Cipher.dll,运行,出现错误信息“找不到DLL入口点(Error 53)”。出现这一错误的原因是C++编译器在编译时对函数名Encrypt作了修改。打开快速查看程序(D:\WINNT\System32\Viewers\QuikView.exe,Cipher.dll拖入查看窗口,找到字段?Encrypt@@YAHHH@Z,发现函数名被加了一串字符。
      解决方法有二。第一,直接在
    VB声明中将“?Encrypt@@Y AHHH@Z”作为别名放在“Alias”后即可;第二,在Cipher.dll代码中在语句“__declspec(dllexport) int __stdcall Encrypt(int p, int k);”前加上“extern "C" ”,编译后,用QuikView查看,函数名变为“_Encrypt”,之后再在VB声明中做相应调整即可。
     (对于使用宏的
    DLL,在“#define”语句中,对宏“Cipher_API”的替换值做更改即可。)
      进行了③的更改后,程序又找不到入口点了。再用
    QuikView查看,发现函数名变为_Encrypt@8”。还有解决方法。在Cipher.dll工程中添加一个文本文件,命名为“Cipher.def,添加代码如④。编译后再用QuikView查看,函数名变回“Encrypt”,在VB中调用,运行正常。注意使用了.def文件,就不需要再使用“extern "C" ”了。

    关于调用约定
      采用②中第二种解决方法,运行,出现错误信息“DLL调用约定错误(Error 49)”。原因是调用约定共有5种方式:__fastcall__pascal__stdcall__cdecl__thiscall(成员函数的调用方式,但不能使用它显示声明一个函数),VC++默认调用方式为__cdecl,而VB默认调用方式则为__stdcall。解决方法是,更改代码如下(指定调用方式):

      __declspec(dllexport) int __stdcall Encrypt(int p, int k);
         
    …………

       
    int __stdcall Encrypt(int p, int k)
         {
             int c = p + k;
            
    return c;
        
    }

    源代码
    Cipher.dll
     
    Cipher.cpp

     
    //引入预编译头文件
     
    #include stdafx.h

       #define
    CIPHER_API __declspec(dllexport) 

      
    //
    声明我的函数
     
    CIPHER_API int __stdcall Encrypt( int p, int k );

      
    ……

     
    //DLL入口函数
     
    BOOL APIENTRY DllMain(HANDLE hModule,
                                             
    DWORD ul_reason_for_call,
                                             
    LPVOID lpReserved)

       {
           switch (ul_reason_for_call)
          
    {
           case DLL_PROCESS_ATTACH: 
           case DLL_THREAD_ATTACH: 
           case DLL_THREAD_DETACH: 
           case DLL_PROCESS_DETACH:
               break;
           }
           return TRUE;
       }

       //
    我的函数
       int __stdcall Encrypt(int p, int k)
       {
           int c = p + k;
           return c;
       }

    ……

    Cipher.def
      LIBRARY Cipher
      EXPORTS Encrypt

    编译后,将Cipher.dll复制到VB程序可执行文件所在目录。

    VB中调用:
      Option Explicit
      Private
    Declare Function Encrypt Lib Cipher (ByVal p As Long, ByVal k As Long) As Long

      Private Sub Form_Load()
      Dim c As Long
      c = Encrypt(24, 8)
      Text1.Text = c
      End Sub

     

  • 相关阅读:
    Microsoft .NET Framework 远程执行代码漏洞
    GE PACSystems RX3i 输入验证漏洞
    Windows10 1809版本Windows自动更新服务无法禁用问题解决方案
    企业网络防范Serv-U的漏洞
    jsp安全问题及其解决建议
    Windows XP系统搜索故障及处理办法点点通
    开启路由器的TCP拦截
    从MyIE2平滑升级到Maxthon的完美方案
    全面解析UNIX缓冲区溢出 深度防御体系
    从异常系统进程检查企业网络安全 (二)
  • 原文地址:https://www.cnblogs.com/ahuo/p/631605.html
Copyright © 2020-2023  润新知