打包使用调试dll以及注意事项

打包dll

如果要打包的函数分布在不同的文件中,在相应的每个头文件和源文件都做如下修改即可。

头文件

1
2
3
4
5
6
7
8
9
#ifdef PREG_API
#define PREG_API_EXPORT _declspec(dllexport)
#else
#define PREG_API_EXPORT _declspec(dllimport)
#endif // PREG_API

PREG_API_EXPORT result *my_detect(char *datacfg, char *cfg, network *net, char *filename, float thresh, float hier_thresh, int *objects_num);

PREG_API_EXPORT network *my_load_weight(char *cfgfile, char *weightfile);

源文件

1
2
3
4
5
6
7
8
9
PREG_API_EXPORT result *my_detect(char *datacfg, char *cfg, network *net, char *filename, float thresh, float hier_thresh, int *objects_num)
{
...
}

PREG_API_EXPORT network* my_load_weight(char *cfgfile, char *weightfile)
{
...
}

配置

exe —> dll

在预编译选项中加入PREG_API

编译程序即可得到 .dll 和 .lib

调用dll

头文件

在CPP文件中调用dll

1
2
3
4
// 使用了extern "C" _declspec(dllimport),main文件必须为cpp文件,否则会出现error C2059: syntax error : 'string'
extern "C" _declspec(dllimport) result *my_detect(char *datacfg, char *cfg, network *net, char *filename, float thresh, float hier_thresh, int *objects_num);

extern "C" _declspec(dllimport) network *my_load_weight(char *cfgfile, char *weightfile);

若想在CPP或者C文件中同时可以使用,下面的extern "C"表示在cpp中使用c语言的规则调用c文件产生的库。

1
2
3
4
5
6
7
8
9
// 这种调用方式可以被main.c与main.cpp使用
#ifdef __cplusplus
extern "C" {
#endif
_declspec(dllimport) result *my_detect(char *datacfg, char *cfg, network *net, char *filename, float thresh, float hier_thresh, int *objects_num);
_declspec(dllimport) network *my_load_weight(char *cfgfile, char *weightfile);
#ifdef __cplusplus
}
#endif

源文件

直接使用即可

dll中结构体

无法使用,直接在调用dll的头文件中声明相同的结构体即可

dll的调试

最新的dll和lib放在调用工程代码相同目录,直接debug,打断点,单步调试,VS会自动查找源文件所在的目录并打开。

注意事项

  • 打包dll的环境(如x64,release)要与调用dll的代码环境设置一致,否则会报错
  • windows下不能将结构体或者结构体指针返回,除非调用子函数的代码中包含子函数的头文件。
  • 若VS调试的时候,出现了跳转不正常,断点的位置不正常,中断所停位置与实际不符等情况,删除中文注释。
  • 当程序涉及到读取文件的时候,注意路径问题。第一种方法是使用绝对路径,第二种方法是使用下面代码打印当前工作目录,对相对路径进行修改。

    1
    2
    3
    4
    5
    6
    7
    8
    // Linux
    char buf[80];
    getcwd(buf,sizeof(buf));
    printf("current working directory: %s\n", buf);
    // windows
    char buf[80];
    _getcwd(buf,sizeof(buf));
    printf("current working directory: %s\n", buf);
  • 在windows下含有static inline的头文件在debug模式下编译报错,在头文件添加下面语句

    1
    2
    3
    #if defined(WIN32) && !defined(__cplusplus)
    #define inline __inline
    #endif
  • 当打包dll的环境在x64,debug下时,调用dll的程序代码目录下要放入打包程序所调用的第三方dll文件,否则提示找不到该dll。但是x64,release下就没有这个问题。

  • 若程序会读取配置文件等信息,又报错了,首先怀疑是路径问题。
  • 调用32位debug版本的时候,注意把库依赖的第三方库也改为32位的。
  • 若没有生成lib,但是有dll,重新生成工程即可。
  • 64位程序训练出的参数文件、配置文件等在32位程序还可以运行,并且32位程序读取文件时仍然按64位文件读。要注意的是,分配给32位程序的内存比64位小,因此可能需要启用大地址。
  • 在Qt下调用dll,若出现传参到dll中的函数后,路径(文件名等)为乱码,可能是参数错位或者参数个数不对。
------ 本文结束------
坚持原创技术分享,您的支持将鼓励我继续创作!

欢迎关注我的其它发布渠道