1112---Windows 环境下 Visual C++ 、GCC 、Visual Basic6 动态访问DLL库应注意的有关事项

Windows 环境下 Visual C++ 、GCC 、Visual Basic6 动态访问DLL库应注意的有关事项

一 前言

前几天,遇到使用古老的Visual Basic6 访问DLL动态库的情况,并顺便探讨了C++ 动态加载DLL的情况,作为总结记录如下。

1 环境

  1. 操作系统:Win10 专业版
  2. Visual studio 2019
  3. mingw-w32 Gcc 在Windows环境的编译器
  4. Visual Basic6

2 提供的资料

DLL 库文件、DLL 库文件中使用的头文件、DLL 库输出函数的说明书

二 探索DLL常用的工具

DLL 库文件有哪些输出函数可供调用?输出函数的偏移地址是多少?这些信息可通过工具进行查看。常用的查看DLL 信息的工具有微软的dumpbin和Nir Sofer 的DLL Export Viewer。

1 dumpbin.exe

dumpbin 包含在 visual studio 开发套件中,可在Tools文件夹下查找。在dumpbin所在的文件夹,打开命令行窗口,执行之。

C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\bin\Hostx86\x64
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\bin\Hostx86\x86
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\bin\Hostx64\x86
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.29.30037\bin\Hostx64\x64

dumpbin /EXPORTS F:\tmp\aeobb32.dll

在这里插入图片描述

2 Nir Sofer 开发的 DLL Export Viewer 工具

  1. 运行 dllexp.exe
  2. 选择 DLL:点击“浏览按钮进行选择”
    在这里插入图片描述
  3. 点击“确认”,输出如下

在这里插入图片描述

三 Visual Basic开发平台使用DLL 的步骤及应注意事项

1 VB中使用DLL中函数的步骤

  1. 数据类型的声明
  2. 使用DLL函数的声明
  3. 调用DLL函数
  4. 关闭DLL库

2 C语言中的类型定义转换为 Visual Basic中的自定义类型

如果DLL不是VB编写的,就涉及到变量类型转换问题。譬如DLL是由C语言编写的,其struct结构类型就必须转换为VB环境下的自定义类型。

// C 语言中的结构类型定义	
struct inpstr
{
	double	vreq;	
	long 	   total;	
	char     fancode[31]; 
	char     serie[4]; 
   float    t_jkgmvv;
};


' 在VB中的类型声明
Type inpstr
  vreq As Double    
  total As Long   
  fancode As String * 31   
  serie As String * 4   
  t_jkgmvv as single  
End Type

3 声明引入DLL的函数

函数声明要严格按照DLL中函数的格式进行,下面举例说明。

Public Declare Function calc_fan  _
Lib "aeobb32.dll" _
Alias "_calc_fan@4" (ByRef inppar As inpstr) _
As Long

在这里插入图片描述

  1. VB中声明的函数名

  2. 动态库文件

  3. 动态库中实际的函数名

  4. 函数参数,使用在VB中转换后的类型

  5. 函数的返回类型

4 应注意的事项

  1. 对字符串的赋值,一般在末尾加上 chr$(0)【因为C语言的字符串是以"\0"作为分隔的,想必是为了确保传入的字符串参数以"\0"结束。
' 给 VB的结构体赋值
    With inppar
        .vreq = 2000
        .total = 1
        .fancode = "" & Chr$(0)
        .serie = "TLZ" & Chr$(0)
        .t_jkgmvv = 23.34
    End With

四 Visual C++ 开发平台动态加载DLL 的步骤及应注意事项

1 首先确定编译类型是32位或是64位

如果 DLL库是32位的,为了确保使用 LoadLibrary函数顺利加载DLL动态库,最好选择 32位编译器。

对于 Visual Studio 2019,在创建项目时,选择
在这里插入图片描述
在这里插入图片描述

2 选择 X86 编译(32位),如果选择 X64,程序会出错。

在这里插入图片描述

3 部分程序源码

#include <iostream>
#include <Windows.h>
#include "aeobb32.h"
#include <string>
#include <stdlib.h>
#include <tchar.h>

//定义引入函数指针
typedef long (WINAPI* FPSETDLLPATH)(char* DLLpath);

typedef long (WINAPI* FPcalc_fan)(const struct inpstr* InpPar);

typedef long (WINAPI* FPget_working_data)(struct outstr* const OutRow, long Row);


int main()
{
    struct inpstr inpstr_;
    struct outstr out_;

    inpstr_.vreq = 2000;
    inpstr_.preq = 1000;
    inpstr_.diameter = 0;
    inpstr_.rotq = 1.2;
    inpstr_.ro20 = 1.2;
    inpstr_.total = 1;
    inpstr_.debug_level = 0;
    strcpy_s(inpstr_.fancode, "");
    strcpy_s(inpstr_.serie, "TLZ");
    inpstr_.isfreout = 1;


    FPSETDLLPATH  SETDLLPATH;
    FPcalc_fan  calc_fan;
    FPget_working_data get_working_data;


    HINSTANCE hInstLibrary = LoadLibrary(_T("E:\\tmp\\LoadDll_test\\aeobb32.dll"));

    SETDLLPATH = (FPSETDLLPATH)GetProcAddress(hInstLibrary, "_SETDLLPATH@4");
    calc_fan = (FPcalc_fan)GetProcAddress(hInstLibrary, "_calc_fan@4");
    get_working_data = (FPget_working_data)GetProcAddress(hInstLibrary, "_get_working_data@8");


    char DLLpath[] = "E:\\tmp\\LoadDll_test\\database";

    long lRet = SETDLLPATH(DLLpath);
    long CalcRis = calc_fan(&inpstr_);
    //long out_result = get_working_data(&out_, CalcRis);
    long out_result = get_working_data(&out_, 0);

    printf("sizeof  char:%d  \n", sizeof(out_.t_codven));
    printf("sizeof  long:%d  \n", sizeof(out_.t_palava));
    printf("sizeof  float:%d  \n", sizeof(out_.t_jkgmvv));
    printf("sizeof  double:%d  \n", sizeof(out_.t_phifun));

    printf("t_codven:%s  \n", out_.t_codven);
    printf("t_palava:%d  \n", out_.t_palava);
    printf("t_jkgmvv:%f  \n",out_.t_jkgmvv);
    printf("t_phifun:%f  \n", out_.t_phifun);

    FreeLibrary(hInstLibrary);

    getchar();

}

4 类型的转换问题

如果形参的类型是 LPCWSTR,如果实参是"const char *" 类型,必须进行转换,宏 _T是转换方式之一。

_T("E:\\tmp\\LoadDll_test\\aeobb32.dll")

五 mingw即Gcc 开发平台动态加载DLL库文件的步骤及应注意事项

如果 DLL库是32位的,为了确保使用 LoadLibrary函数顺利加载DLL动态库,编译器最好选择 32位编译器。其它方面与Visual studio 相同。

2022-11-12

*" 类型,必须进行转换,宏 _T是转换方式之一。

_T("E:\\tmp\\LoadDll_test\\aeobb32.dll")

五 mingw即Gcc 开发平台动态加载DLL库文件的步骤及应注意事项

如果 DLL库是32位的,为了确保使用 LoadLibrary函数顺利加载DLL动态库,编译器最好选择 32位编译器。其它方面与Visual studio 相同。

2022-11-12

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值