吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 424|回复: 29
收起左侧

[其他求助] 求助C++ dll调用-动态(显式) VC2019

  [复制链接]
lysuro 发表于 2024-3-31 21:11
50吾爱币
dll文件(32位)和Api文档
链接:https://pan.baidu.com/s/1QZuVCbQCG10JQRiEQuexfw?pwd=52pj
提取码:52pj

求助老师写个  "C++ dll调用-动态(显式) "   "NaturalCard.dll"   "device_Open"函数打开设备示例.
本人C++小白,请详细写明.h内代码, .ccp内代码, dll文件放哪个位置等, 希望复制粘贴即用. 谢谢.

函数说明:
device_Open打开设备
定义:打开设备端口
原型:
long device_Open(char* szPort)
参数:
szPort:USB COM1 COM2 COM3…
返回值:
0:                打开设备成功;
非0:        打开设备失败,参考状态码

状态码
IFD_OK        0        执行成功
IFD_ICC_TypeError        -1        卡片类型不对
IFD_ICC_NoExist                -2        无卡
IFD_ICC_NoPower        -3        有卡未上电
IFD_ICC_NoResponse        -4        卡片无应答
IFD_ConnectError        -11        读卡器连接错
IFD_UnConnected        -12        未建立连接(没有执行打开设备函数)
IFD_BadCommand        -13        (动态库)不支持该命令
IFD_ParameterError        -14        (发给动态库的)命令参数错
IFD_CheckSumError                -15        信息校验和出错
IFD_OutTime        -20        超时
IFD_False        -21        执行命令失败

Microsoft Visual Studio Community 2019
版本 16.11.34

最佳答案

查看完整内容

已引发异常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.出现异常的原因可能是函数调用约定不一致导致的。在Windows平台上,默认的函数调用约定是__cdecl,但是有些DLL可能使用了不同的调用约定,比如__stdcall。 ...

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

QvQsuipian 发表于 2024-3-31 21:11
已引发异常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.出现异常的原因可能是函数调用约定不一致导致的。在Windows平台上,默认的函数调用约定是__cdecl,但是有些DLL可能使用了不同的调用约定,比如__stdcall。因此,在使用函数指针时,需要确保函数指针的声明与DLL中函数的调用约定一致。
咱们这里将函数指针的声明改为__stdcall调用约定。在加载DLL时也要相应地使用GetProcAddress。

注意下文件命名,写在首行注释里了
[C++] 纯文本查看 复制代码
// 头文件 NaturalCardWrapper.h

#ifndef NATURALCARDWRAPPER_H
#define NATURALCARDWRAPPER_H

#include <Windows.h>

// 函数指针类型定义,使用__stdcall调用约定
typedef long (__stdcall *DeviceOpenFunc)(char);

// 加载DLL并获取函数地址
DeviceOpenFunc LoadAndGetDeviceOpenFunc();

// 释放DLL
void FreeDeviceOpenFunc(HMODULE hDLL);

#endif // NATURALCARDWRAPPER_H


[C++] 纯文本查看 复制代码
// 源文件 NaturalCardWrapper.cpp

#include <iostream>
#include <Windows.h>
#include "NaturalCardWrapper.h"

// 加载DLL并获取device_Open函数的地址
DeviceOpenFunc LoadAndGetDeviceOpenFunc() {
    // 加载DLL
    HMODULE hDLL = LoadLibraryA("NaturalCard.dll");
    if (hDLL == nullptr) {
        std::cerr << "Error loading DLL: NaturalCard.dll" << std::endl;
        return nullptr;
    }

    // 获取device_Open函数的地址  
    DeviceOpenFunc deviceOpenFunc = (DeviceOpenFunc)GetProcAddress(hDLL, "device_Open");  
    if (deviceOpenFunc == nullptr) {  
        std::cerr << "Error getting function address: device_Open" << std::endl;  
        FreeLibrary(hDLL);  
        return nullptr;  
    }  
   
    return deviceOpenFunc;  
}

// 释放DLL
void FreeDeviceOpenFunc(HMODULE hDLL) {
    FreeLibrary(hDLL);
}

int main() {
    // 加载DLL并获取device_Open函数的地址
    DeviceOpenFunc deviceOpen = LoadAndGetDeviceOpenFunc();
    if (deviceOpen == nullptr) {
        std::cerr << "Failed to load and get function address." << std::endl;
        return 1;
    }

    // 调用device_Open函数  
    const char* szPort = "COM1"; // 替换为你的端口号  
    long status = deviceOpen(const_cast<char*>(szPort));  
   
    // 检查返回值  
    if (status == 0) {  
        std::cout << "Device successfully opened on port: " << szPort << std::endl;  
    } else {  
        std::cout << "Failed to open device on port: " << szPort  
                  << ", error code: " << status << std::endl;  
    }  
   
    // 释放DLL  
    HMODULE hDLL = GetModuleHandleA("NaturalCard.dll");  
    if (hDLL) {  
        FreeDeviceOpenFunc(hDLL);  
    }  
   
    return 0;  
}
QvQsuipian 发表于 2024-4-1 00:58
我将假设你已经将`NaturalCard.dll`放置在你的项目文件夹中。
你要创建一个`.h`文件来声明`device_Open`函数的原型,然后创建一个`.cpp`文件来实现调用这个函数的逻辑。
[C] 纯文本查看 复制代码
// NaturalCardWrapper.h

#ifndef NATURALCARDWRAPPER_H
#define NATURALCARDWRAPPER_H

#ifdef __cplusplus
extern "C" {
#endif

// 声明 device_Open 函数原型
long device_Open(char* szPort);

#ifdef __cplusplus
}
#endif

#endif // NATURALCARDWRAPPER_H




[C] 纯文本查看 复制代码
// NaturalCardWrapper.cpp

#include "NaturalCardWrapper.h"
#include <iostream>

// 调用 DLL 中的 device_Open 函数
long openDevice(const char* port) {
    long result = device_Open(const_cast<char*>(port));
    return result;
}

int main() {
    // 例子:打开设备端口 COM1
    const char* port = "COM1";
    
    // 调用打开设备函数
    long status = openDevice(port);
    
    // 检查返回值
    if (status == 0) {
        std::cout << "设备成功打开!" << std::endl;
    } else {
        std::cout << "设备打开失败,错误码:" << status << std::endl;
    }

    return 0;
}

在这里面,`NaturalCardWrapper.h`文件中声明了`device_Open`函数的原型。而`NaturalCardWrapper.cpp`文件中则实现了一个简单的函数`openDevice`,用于调用`device_Open`函数。在`main`函数中,你可以传入想要打开的设备端口,然后调用`openDevice`函数来尝试打开设备。根据返回值,你可以判断设备是否成功打开。
你需要将这两个文件添加到你的项目中,并确保在项目设置中链接`NaturalCard.dll`
ZhaoYF 发表于 2024-4-1 08:47
QvQsuipian 发表于 2024-4-1 00:58
我将假设你已经将`NaturalCard.dll`放置在你的项目文件夹中。
你要创建一个`.h`文件来声明`device_Open`函 ...

楼主要求的是显式调用
你这是隐式调用啊
应该用LoadLibrary()
GetProcAddress()
FreeLibrary()
重改一下吧

免费评分

参与人数 1吾爱币 +1 收起 理由
lysuro + 1 热心回复!

查看全部评分

QvQsuipian 发表于 2024-4-1 10:21
那就cpp文件改一下
[C++] 纯文本查看 复制代码
#include <iostream>
#include <Windows.h>

// 声明函数指针类型
typedef long (*DeviceOpenFunc)(char*);

int main() {
    // 加载 DLL
    HINSTANCE hDLL = LoadLibrary("NaturalCard.dll");
    if (!hDLL) {
        std::cout << "无法加载 DLL 文件。" << std::endl;
        return 1;
    }

    // 获取函数地址
    DeviceOpenFunc device_Open = (DeviceOpenFunc)GetProcAddress(hDLL, "device_Open");
    if (!device_Open) {
        std::cout << "无法获取函数地址。" << std::endl;
        FreeLibrary(hDLL); // 释放 DLL
        return 1;
    }

    // 调用函数
    char port[] = "COM1"; // 例子:打开设备端口 COM1
    long status = device_Open(port);

    // 检查返回值
    if (status == 0) {
        std::cout << "设备成功打开!" << std::endl;
    } else {
        std::cout << "设备打开失败,错误码:" << status << std::endl;
    }

    // 释放 DLL
    FreeLibrary(hDLL);

    return 0;
}
QvQsuipian 发表于 2024-4-1 10:31
更新完整的代码:使用 LoadLibrary() 加载 DLL,然后通过 GetProcAddress() 获取函数地址,最后通过函数指针调用 DLL 中的函数。在程序末尾,使用 FreeLibrary() 释放 DLL
[C++] 纯文本查看 复制代码
// NaturalCardWrapper.h

#ifndef NATURALCARDWRAPPER_H
#define NATURALCARDWRAPPER_H

#include <Windows.h>

// 声明函数指针类型
typedef long (*DeviceOpenFunc)(char*);

// 声明显式加载 DLL 的函数
HMODULE LoadNaturalCardDLL();
void FreeNaturalCardDLL(HMODULE hDLL);

#endif // NATURALCARDWRAPPER_H




[C++] 纯文本查看 复制代码
#include "NaturalCardWrapper.h"
// NaturalCardWrapper.cpp
#include <iostream>

// 定义函数指针
DeviceOpenFunc device_Open = nullptr;

HMODULE LoadNaturalCardDLL() {
    // 加载 DLL
    HMODULE hDLL = LoadLibrary("NaturalCard.dll");
    if (!hDLL) {
        std::cout << "无法加载 DLL 文件。" << std::endl;
        return nullptr;
    }
    
    // 获取函数地址
    device_Open = (DeviceOpenFunc)GetProcAddress(hDLL, "device_Open");
    if (!device_Open) {
        std::cout << "无法获取函数地址。" << std::endl;
        FreeLibrary(hDLL); // 释放 DLL
        return nullptr;
    }

    return hDLL;
}

void FreeNaturalCardDLL(HMODULE hDLL) {
    if (hDLL) {
        FreeLibrary(hDLL); // 释放 DLL
    }
}

int main() {
    // 加载 DLL
    HMODULE hDLL = LoadNaturalCardDLL();
    if (!hDLL) {
        return 1;
    }

    // 调用函数
    char port[] = "COM1"; // 例子:打开设备端口 COM1
    long status = device_Open(port);

    // 检查返回值
    if (status == 0) {
        std::cout << "设备成功打开!" << std::endl;
    } else {
        std::cout << "设备打开失败,错误码:" << status << std::endl;
    }

    // 释放 DLL
    FreeNaturalCardDLL(hDLL);

    return 0;
}

免费评分

参与人数 1热心值 +1 收起 理由
lysuro + 1 热心回复!

查看全部评分

 楼主| lysuro 发表于 2024-4-1 10:48
QvQsuipian 发表于 2024-4-1 10:31
更新完整的代码:使用 LoadLibrary() 加载 DLL,然后通过 GetProcAddress() 获取函数地址,最后通过函数指 ...

你好,感谢帮助

第10行  HMODULE hDLL = LoadLibrary("NaturalCard.dll");"NaturalCard.dll" 红色波浪线报错

严重性        代码        说明        项目        文件        行        禁止显示状态
错误(活动)        E0167        "const char *" 类型的实参与 "LPCWSTR" 类型的形参不兼容        Project1        E:\c++\source\repos\Project1\Project1\NaturalCardWrapper.cpp        10       
 楼主| lysuro 发表于 2024-4-1 10:56
QvQsuipian 发表于 2024-4-1 10:31
更新完整的代码:使用 LoadLibrary() 加载 DLL,然后通过 GetProcAddress() 获取函数地址,最后通过函数指 ...

运行后提示如下:

严重性        代码        说明        项目        文件        行        禁止显示状态
错误(活动)        E0167        "const char *" 类型的实参与 "LPCWSTR" 类型的形参不兼容        Project1        E:\c++\source\repos\Project1\Project1\NaturalCardWrapper.cpp        19       

严重性        代码        说明        项目        文件        行        禁止显示状态
错误        C2664        “HMODULE LoadLibraryW(LPCWSTR)”: 无法将参数 1 从“const char [16]”转换为“LPCWSTR”        Project1        E:\c++\source\repos\Project1\Project1\NaturalCardWrapper.cpp        19       
QvQsuipian 发表于 2024-4-1 11:18
lysuro 发表于 2024-4-1 10:56
运行后提示如下:

严重性        代码        说明        项目        文件        行        禁止显示状态

cpp文件改一下
[C++] 纯文本查看 复制代码
#include "NaturalCardWrapper.h"
#include <iostream>
#include <string>
#include <Windows.h>

// 定义函数指针
DeviceOpenFunc device_Open = nullptr;

HMODULE LoadNaturalCardDLL() {
    // 将字符串转换为宽字符
    const char* dllName = "NaturalCard.dll";
    std::wstring wideDllName(dllName, dllName + strlen(dllName));
    
    // 加载 DLL
    HMODULE hDLL = LoadLibraryW(wideDllName.c_str());
    if (!hDLL) {
        std::cout << "无法加载 DLL 文件。" << std::endl;
        return nullptr;
    }
    
    // 获取函数地址
    device_Open = (DeviceOpenFunc)GetProcAddress(hDLL, "device_Open");
    if (!device_Open) {
        std::cout << "无法获取函数地址。" << std::endl;
        FreeLibrary(hDLL); // 释放 DLL
        return nullptr;
    }

    return hDLL;
}

void FreeNaturalCardDLL(HMODULE hDLL) {
    if (hDLL) {
        FreeLibrary(hDLL); // 释放 DLL
    }
}

int main() {
    // 加载 DLL
    HMODULE hDLL = LoadNaturalCardDLL();
    if (!hDLL) {
        return 1;
    }

    // 调用函数
    char port[] = "COM1"; // 例子:打开设备端口 COM1
    long status = device_Open(port);

    // 检查返回值
    if (status == 0) {
        std::cout << "设备成功打开!" << std::endl;
    } else {
        std::cout << "设备打开失败,错误码:" << status << std::endl;
    }

    // 释放 DLL
    FreeNaturalCardDLL(hDLL);

    return 0;
}
 楼主| lysuro 发表于 2024-4-1 11:35
QvQsuipian 发表于 2024-4-1 11:18
cpp文件改一下
[mw_shl_code=cpp,true]#include "NaturalCardWrapper.h"
#include

你好, 上一步的报错已消失, 运行结果如下:
已引发异常:
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.
百度翻译:
运行时检查失败#0-ESP的值没有在函数调用中正确保存。这通常是用另一个调用约定声明的函数指针调用用一个调用惯例声明的函数的结果。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-5-14 19:33

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表