关于DLL的一些尝试

标签:工程


什么是DLL

(跟ddl很相近哈……)
由独立的程序模块创建得到动态链接库(Dynamic Linkable Library)文件,可单独进行编译和测试。只有在EXE 程序确实要调用这些DLL模块的情况下,系统才会将它们装载到内存空间中。

只要遵循约定的DLL接口规范和调用方式,用各种语言编写的DLL都可以相互调用。譬如Windows提供的系统DLL(其中包括了Windows的API),在任何开发环境中都能被调用,不在乎其是Visual Basic、Visual C++还是Delphi。


静态库小测试

生成LIB

// test.h
#ifndef LIB_H
#define LIB_H
extern "C" int add(int x, int y);
#endif
// test.cpp
#include "test.h"
int add(int x, int y)
{
    return x + y;
}

编译生成test.lib,如果是在VS里的话,项目右键->属性->常规->项目默认值->配置类型->静态库,编译即可生成。

调用LIB

#include <stdio.h>
#include <iostream>
#include "..\\..\\test.h"  // 路径什么的根据自己电脑的来
#pragma comment( lib, "..\\..\\..\\debug\\test.lib" )  //指定与静态库一起连接   
int main(int argc, char* argv[])
{
    printf("2 + 3 = %d", add(2, 3));
    system("pause");
}

test.h在这里会作为外部依赖项出现。
经测试,三个文件里函数名必须要统一,否则就算lib能够生成也不能调用。

以上,我很奇怪为什么在生成以及后面调用要多次#include "test.h" 一旦没有两个工程生成解决方案都会错,哭泣。


动态库小测试

生成DLL之dllexport语句

// test.h
#ifndef LIB_H
#define LIB_H
extern "C" int __declspec(dllexport)add(int x, int y);
#endif

__declspec(dllexport)语句声明函数add为DLL的导出函数,就是说这个函数可以被其他程序调用,即作为DLL的一个对外函数接口。
反之若是dllimport,则声明一个导入函数,是说这个函数是从别的DLL导入的。

// test.cpp
#include "test.h"
int add(int x, int y)
{
    return x + y;
}

编译生成test.dll,如果是在VS里的话,项目右键->属性->常规->项目默认值->配置类型->动态库,编译即可生成。

动态调用DLL

#include <stdio.h>   
#include <windows.h>   

typedef int(*lpAddFun)(int, int); //宏定义函数指针类型   

int main(int argc, char *argv[])
{
    HINSTANCE hDll; //DLL句柄    
    lpAddFun addFun; //函数指针   

    hDll = LoadLibrary("..\\..\\..\\debug\\test.dll");
    if (hDll != NULL) {
        addFun = (lpAddFun)GetProcAddress(hDll, "add");
        if (addFun != NULL) {
            int result = addFun(2, 3);
            printf("%d", result);
        }
        FreeLibrary(hDll);
    }
    return 0;
}

这里不用#include "test.h",同时也是种动态调用,可以人为选择需要的函数选择加载、调用和释放。

生成DLL之.def文件

采用模块定义(.def)文件声明,提供了有关被链接程序的导出、属性及其他方面的信息。第一行为dll的名称,exports后面为导出的函数名,并指定其序号。

LIBRARY temptest 
EXPORTS   
add @ 1

有了这个文件以后,前面的test.h就可以不要了。
可以用
addFun = (lpAddFun)GetProcAddress(hDll, MAKEINTRESOURCE(1));
语句来调用add函数。

静态调用DLL

与前面的动态相对的,还有静态调用方式。由编译系统完成对DLL的加载和应用程序结束时 DLL 的卸载。

#include <stdio.h>   
#include <windows.h>   

#pragma comment(lib, "test.lib") 
//.lib文件中仅仅是关于其对应DLL文件中函数的重定位信息   

extern "C" int __declspec(dllimport) add(int x, int y);

int main(int argc, char* argv[])
{
    int result = add(2, 3);
    printf("%d\n", result);
    return 0;
}

一直报错error LNK2019,这里已经把test.libtest.dll拷到工程文件夹下面了。并且动态调用dll可行,除非是lib文件有问题。


错误信息

error MSB8020
项目右键->属性->常规->平台工具集 选择电脑上安装好的版本,如v140

error C3872: “0x3000”
检查一下代码里是不是有中文全角空格,删掉即可。

LNK1107: 文件无效或损坏
附加依赖项误把一个lib项写成了dll

error LNK2019: 无法解析的外部符号 __imp__xxx,该符号在函数 _xxxxx 中被引用
一般这种错误加个函数的lib文件到附加依赖项就好了。


预告

VB调用C++的DLL…铺垫了半天还是不会啊……

猜你喜欢

转载自blog.csdn.net/danliwoo/article/details/69935928