关于VS2019编译环境下的问题_DLL

求解
麻烦解决一下吧[哭][哭]
搜网上的方法好多都不管用
还是这个动态链接库的问题
[无奈]
这个是报的错
我的环境是VS2019专业版

img

Status.c
#pragma once

#ifndef BHDLL_d
#define BHDLL_d
//宏定义导出
#define BHDLL__
#ifdef BHDLL__//如果没有定义DLLH 就定义 DLLH __declspec(dllexport)
#define BHDLL __declspec(dllexport)//导出
#else
#define BHDLL __declspec(dllimport)//导入
#endif // DLLH__//如果没有定义DLLH 就定义 DLLH 

#include <stdio.h>
#include <string.h>
#include <stdarg.h> // 提供宏va_list、va_start、va_arg、va_end
#include <ctype.h>  // 提供isprint原型
#include "Status.h"

/* 全局变量*/
Boolean debug = FALSE;  // 是否使用debug模式。测试时可设置为TRUE,发布时可设置为FALSE(修改debug值后,一般需要重新生成静态库)。


/*
 * 从文件中读取预设的英文符号
 *
 * 这是自定义的数据录入函数,用于从文件fp中读取格式化的输入,
 * 与fscanf的不同之处在于此函数只会读取英文字符,对于中文字符,则直接跳过。
 *
 * 注:
 * 1. 这里约定所有格式串为简单形式,如:%d%c%s等,而不是%2d%5s等
 * 2. 读取字符串时,遇到空格或非打印字符会停止读取
 */
BHDLL int ReadData(FILE* fp, char* format, ...) {
    int* i;     // 存储读取到的整型
    float* f;   // 存储读取到的浮点型
    char* ch;   // 存储读取到的字符型
    char* s;    // 存储读取到的字符串型
    
    int n;      // 遍历存储字符串的字符数组
    
    int len;    // 格式串format的长度
    int k;      // 遍历格式串时的游标
    
    int tmp;    // 暂存从文件中读取到的字符
    
    va_list ap; // 可变参数指针,指向存储数据的变量
    
    // 累计成功读取到的字符数
    int count = 0;
    
    
    /*
     * 获取格式串的长度
     * 这里预设格式串仅由简单
     */
    len = strlen(format);
    
    // ap指向首个可变参数
    va_start(ap, format);
    
    // 只遍历奇数索引,因为偶数索引下都是%
    for(k = 1; k <= len; k = k + 2) {
        // 跳过所有非西文字符
        while((tmp = getc(fp)) != EOF) {
            // 遇到首个西文字符,将此西文字符重新放入输入流
            if((tmp >= 0 && tmp <= 127)) {
                ungetc(tmp, fp);
                break;
            }
        }
        
        // 如果已读到文件结尾,结束读取
        if(tmp == EOF) {
            break;
        }
        
        // 遇到了"%c",应该读取字符
        if(format[k] == 'c') {
            ch = va_arg(ap, char*);
            
            count += fscanf(fp, "%c", ch);
        }
        
        // 遇到了"%d",应该读取整型
        if(format[k] == 'd') {
            i = va_arg(ap, int*);
            
            while((tmp = getc(fp)) != EOF) {
                // 寻找整数区域
                if((tmp >= '0' && tmp <= '9') || tmp == '-' || tmp == '+') {
                    ungetc(tmp, fp);
                    break;
                }
            }
            
            if(tmp != EOF) {
                count += fscanf(fp, "%d", i);
            }
        }
        
        // 读取浮点型,一律存储为double类型
        if(format[k] == 'f') {
            f = va_arg(ap, float*);
            
            while((tmp = getc(fp)) != EOF) {
                if((tmp >= '0' && tmp <= '9') || tmp == '-' || tmp == '+' || tmp == '.') {
                    ungetc(tmp, fp);
                    break;
                }
            }
            
            if(tmp != EOF) {
                count += fscanf(fp, "%f", f);
            }
        }
        
        // 读取字符串
        if(format[k] == 's') {
            s = va_arg(ap, char*);
            
            n = 0;
            
            // 查找排除空格的可打印字符
            while((tmp = getc(fp)) != EOF && (!isprint(tmp) || tmp == ' ')) {
            }
            
            // 如果未到文件结尾
            if(!feof(fp)) {
                
                // 将上面读到的字符重新放入流中
                ungetc(tmp, fp);
                
                while((tmp = getc(fp)) != EOF) {
                    // 存储排除空格的可打印字符
                    if(isprint(tmp) && tmp != ' ') {
                        s[n++] = tmp;
                    } else {
                        ungetc(tmp, fp);
                        break;
                    }
                }
                
                count++;
            }
            
            // 字符串最后一个字符为空字符
            s[n] = '\0';
        }
    }// for
    
    va_end(ap);
    
    return count;
}

/*
 * 摁下回车键以继续运行。
 *
 * 通常在测试阶段时,需要让每一步测试都暂停下来,以观察其输出,此时可以让debug=TRUE。
 * 在发布时,可以让debug=FALSE,此时各个测试块将不会暂停。
 */
BHDLL void PressEnterToContinue(Boolean debug) {
    fflush(stdin);
    
    // 处于测试阶段时,可以让debug=TRUE,手动输入换行,以便让程序暂停下来,观察每一步的输出
    if(debug) {
        printf("\nPress Enter to Continue...");
        getchar();
        
        // 发布时,可以让debug=FALSE,自动添加换行,直接出结果
    } else {
        printf("\n");
    }
    
    fflush(stdin);
}

/*
 * 函数暂停一段时间。
 *
 * time不代表具体的时间,只是代表一段时间间隔,
 * 通过调节time的大小,可以使程序暂停适当的时间后继续运行。
 */
BHDLL void Wait(long time) {
    double i;
    
    if(time<0) {
        time = -time;
    }
    
    for(i = 0.01; i <= 100000.0 * time; i += 0.01) {
        // 空循环
    }
}

/*
 * 跳过空白,寻找下一个"可读"符号。
 *
 * 此方法常用在读取字符的语句之前,这会跳过遇到目标字符之前的空白符号,
 * 比如跳过'\r'、'\n'、'\r\n'、' '、'\t'、'\f'。
 */
BHDLL void skipBlank(FILE* fp) {
    int ch;
    
    if(fp == NULL) {
        return;
    }
    
    while((ch = getc(fp)) != EOF) {
        // 如果遇到ANSI码之外的符号,比如汉字,则直接跳过
        if(ch >= 0 && ch <= 127) {
            // 如果遇到的ANSI码不是空白,比如'\r'、'\n'、'\r\n'、' '、'\t'、'\f',则表示该符号"可读"
            if(ch != '\r' && ch != '\n' && ch != ' ' && ch != '\t' && ch != '\f') {
                // 将"可读"符号放入输入流,以待后续工具来读取它
                ungetc(ch, fp);
                break;  // 可以跳出循环了,因为已经找到了"可读"符号
            }
        }
    }
}
#endif

Status.h头文件
/*
 * 注:
 * 本次修订的目的包括降低耦合,争取每个模块都可以单独运行
 * 但是Status这个模块会被所有其他模块引用,引用次数很多。
 * 如果直接将Status模块复制到其它模块中,则会导致太多重复代码,
 * 因此这里生成一个公共静态库让其它模块共享比较划算
 */
#ifndef STATUS_H
#define STATUS_H

#include <stdio.h>

/* 状态码 */
#define TRUE        1   // 真/是
#define FALSE       0   // 假/否
#define OK          1   // 通过/成功
#define ERROR       0   // 错误/失败

//系统中已有此状态码定义,要防止冲突
#ifndef OVERFLOW
#define OVERFLOW    -2  //堆栈上溢
#endif

//系统中已有此状态码定义,要防止冲突
#ifndef NULL
#define NULL ((void*)0)
#endif

/* 状态码类型 */
typedef int Status;

/* 布尔类型 */
typedef int Boolean;


/* 全局变量*/
extern Boolean debug;   // 是否使用debug模式


/*
 * 从文件中读取预设的英文符号
 *
 * 这是自定义的数据录入函数,用于从文件fp中读取格式化的输入,
 * 与fscanf的不同之处在于此函数只会读取英文字符,对于中文字符,则直接跳过。
 *
 * 注:
 * 1. 这里约定所有格式串为简单形式,如:%d%c%s等,而不是%2d%5s等
 * 2. 读取字符串时,遇到空格或非打印字符会停止读取
 */
BHDLL int ReadData(FILE* fp, char* format, ...);

/*
 * 摁下回车键以继续运行。
 *
 * 通常在测试阶段时,需要让每一步测试都暂停下来,以观察其输出,此时可以让debug=TRUE。
 * 在发布时,可以让debug=FALSE,此时各个测试块将不会暂停。
 */
BHDLL void PressEnterToContinue(Boolean debug);

/*
 * 函数暂停一段时间。
 *
 * time不代表具体的时间,只是代表一段时间间隔,
 * 通过调节time的大小,可以使程序暂停适当的时间后继续运行。
 */
BHDLL void Wait(long time);

/*
 * 跳过空白,寻找下一个"可读"符号。
 *
 * 此方法常用在读取字符的语句之前,这会跳过遇到目标字符之前的空白符号,
 * 比如跳过'\r'、'\n'、'\r\n'、' '、'\t'、'\f'。
 */
BHDLL void skipBlank(FILE* fp);

#endif

你真的有认真看人家怎么做的吗?把你源文件(Status.c)中include前面那些放到头文件中(Status.h)中

https://blog.csdn.net/LonelyBHBH/article/details/124422914

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7407568
  • 我还给你找了一篇非常好的博客,你可以看看是否有帮助,链接:关于 C#调用C库Dll,有回调函数时,只执行一次回调函数就直接挂掉 的解决方法
  • 除此之外, 这篇博客: 创建动态链接库(dll)中的 解决函数名字改编的问题:模块定义文件(.DEF) 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • LIBRARY MYDLL3
    
    EXPORTS
       add
       subtract

    定义规则

    entryname[=internal_name|other_module.exported_name] [@ordinal [NONAME] ] [ [PRIVATE] | [DATA] ]

    参考文档:微软官方说明

    EXPORTS
       DllCanUnloadNow      @1          PRIVATE
       DllWindowName = WindowName       DATA
       DllGetClassObject    @4 NONAME   PRIVATE
       DllRegisterServer    @7
       DllUnregisterServer
  • 您还可以看一下 夏曹俊老师的网络小说抓取软件的设计与研发——来自企业开发实践经验课程中的 dll中public方法与业务逻辑-章节内容获取小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    针对这个问题,可能的解决方案如下:

    1. 确认dll文件是否存在或正确: 首先,需要确认出现错误的dll文件是否存在,如果存在,再检查dll文件是否正确。可以尝试重新生成一下dll文件并替换原来的文件,并且确保dll文件与可执行文件固若定位。

    2. 确认dll文件的使用方式是否正确: 检查是否使用LoadLibrary和GetProcAddress函数正确加载和调用dll函数。如果不确定,可以查看微软官方文档并尝试按文档中的示例编写代码 微软官方文档

    3. 确认dll文件的依赖性是否正确: 检查是否缺少引用的库文件或依赖的dll文件。可以使用Dependency walker工具查看dll文件的依赖项,以便确认何时出现问题。 如果确实是依赖项问题,则需要确保这些依赖项可用并在正确的位置。 还可以尝试使用/sysinternals的pslist和pskill等工具结束有关进程,确保dll不存在于Memory中。 Dependency Walker下载链接

    4. 确认dll文件的导出是否正确: 可以通过创建自己的模块定义文件(.DEF)为导出函数命名,从而确保正确的导出函数名称。 可以在导入dll时指定使用已经定义的名称,而不是默认导出名称,以避免名称冲突。 微软官方文档

    如果以上解决方案都不奏效,建议重新安装VS2019环境,可能存在环境配置错误不可避免,一些DLL在VS进行开发时需要更多的依赖项,比如SDK,光盘中的Visual C邮件流,.NET框架更新等等。

    祝您好运!

我好像是在头文件函数前也加了BHDLL所以错了