VS---《在VS2010中 使用C++创建和使用DLL》(002)

VS---《在VS2010中 使用C++创建和使用DLL》(002)

  前面初认识了创建和调用DLL,在VS工程下可以通过在 同一工程、不同工程 下创建和调用DLL。现在,同一工程下创建和调用DLL,实现三种方式的创建和调用DLL:

(1)加载时动态链接方式调用DLL---用到_declspec(dllimport)

(2)运行时动态链接方式调用DLL---用到LoadLibrary()

(3)以.def文件(模块定义文件)方式导出函数

   按其它方式,也可以分为:

(1)静态调用DLL:添加“XXX.lib”,然后#include "XXX.h",把XXX.lib(引入库文件)、XXX.DLL(动态库文件)、XXX.h(头文件)全部放到工程目录下。

(2)动态调用DLL:通过LoadLibrary、GetProcAddress、FreeLibrary实现。

**********************************************************************************************

**********************************************************************************************

**********************************************************************************************

**********************************************************************************************

//====================================================================
// 文件: DellDemo.h
//====================================================================

#ifndef _DLL_H_
#define _DLL_H_

#ifdef DLLProvider
#define EXPORTS_DELL_DEMO _declspec( dllexport )
#else
#define DLL_EXPORT_IMPORT _declspec(dllimport)
#endif
extern "C" DLL_EXPORT_IMPORT int Add (int a , int b);
#endif

/*
#ifndef _MYCODE_H_
#define _MYCODE_H_
#ifdef DLLDEMO1_EXPORTS
#define EXPORTS_DEMO _declspec( dllexport )
#else
#define EXPORTS_DEMO _declspec(dllimport)
#endif
extern "C" EXPORTS_DEMO int Add (int a , int b);
#endif
*/
//====================================================================
// 文件: DellDemo.cpp
//====================================================================

#include "DellDemo.h"
int Add ( int a , int b )
{
    return ( a + b );
}
/*
    作者:WP @20160627
    功能:学习制作DLL、调用DLL。
          test_Dell.cpp : 定义控制台应用程序的入口点。
    方法:
          (1)加载时动态链接方式调用DLL---用到_declspec(dllimport)
          (2)运行时动态链接方式调用DLL---用到LoadLibrary()
          (3)以.def文件(模块定义文件)方式导出函数
*/

//-------------------------------(1)加载时动态链接方式调用DLL-------------------------
//在提供者那里, 方法被声明为__declspec(dllexport)
//在使用者那里,方法被声明为__declspec(dllimport)
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <stdio.h>

//#include "..\Dell_001\DellDemo.h"
using namespace std;

//注意:导入库文件的目录必须在本工程的目录下,也就是说要把生成的dll和lib文件都要拷贝到该工程的目录下,
//因为不再该目录下,尽管修改了路径,仍然提示找不到DllDemo.dll
#pragma comment(lib, "..\debug\Dell_001.lib")              //添加lib路径    
extern "C" _declspec(dllimport) int Add(int a, int b);    //DLL输出:提供者申明 + 输出函数名

int _tmain(int argc, _TCHAR* argv[])
{
        cout<<Add(2, 3)<<endl;
        while(1);//程序运行到这,方便看运行结果
            return 0;
}
/*
    作者:WP @20160627
    功能:学习制作DLL、调用DLL。
          test_Dell.cpp : 定义控制台应用程序的入口点。
    方法:
          (1)加载时动态链接方式调用DLL---用到_declspec(dllimport)
          (2)运行时动态链接方式调用DLL---用到LoadLibrary()
          (3)以.def文件(模块定义文件)方式导出函数
*/

//-------------------------------(2)运行时动态链接方式调用DLL---用到LoadLibrary()-------------------------
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include<stdio.h>

using namespace std;

typedef int (*AddFunc)(int a, int b);

int _tmain(int argc, _TCHAR* argv[])
{

    HMODULE hDll = LoadLibrary(_T("Dell_002.dll"));
    if (hDll != NULL)
    {
        AddFunc add = (AddFunc)GetProcAddress(hDll, "Add");
        if (add != NULL)
        {
            cout<<add(2, 3)<<endl;
        }
        FreeLibrary(hDll);
    }
    while(1);
}

DellDemo.def

LIBRARY  "Dell_003"
EXPORTS
Add @1;Export the Add function
/*
    作者:WP @20160627
    功能:学习制作DLL、调用DLL。
          test_Dell.cpp : 定义控制台应用程序的入口点。
    方法:
          (1)加载时动态链接方式调用DLL---用到_declspec(dllimport)
          (2)运行时动态链接方式调用DLL---用到LoadLibrary()
          (3)以.def文件(模块定义文件)方式导出函数
*/

//-------------------------------(3)以.def文件(模块定义文件)方式导出函数-------------------------
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include<stdio.h>

using namespace std;

typedef int (*AddFunc)(int a, int b);
int _tmain(int argc, _TCHAR* argv[])
{
    HMODULE hDll = LoadLibrary("Dell_003.dll");
    if (hDll != NULL)
    {
        AddFunc add = (AddFunc)GetProcAddress(hDll, MAKEINTRESOURCE(1));
        if (add != NULL)
        {
            cout<<add(2, 3)<<endl;
        }
        FreeLibrary(hDll);
    }
    while(1);
}


其中几点注意:
(1)Module-Definition File(.def)文件的格式如下:
    LIBRARY语句说明.def文件对应的DLL;
    EXPORTS语句后列出要导出函数的名称。可以在.def文件中的导出函数名后加@n,表示要导出函数的序号为n(在进行函数调用时,这个序号有一定的作用)。
    
模块定义文件中的库文件名应和工程名一致。
LIBRARY  "DllDemo"   //这里的字符串名和工程名要一致, 注意这句注释不能放进xxx.def文件中,否则报错
EXPORTS
Add @1;Export the Add function

(2)字符集的问题(是Unicode字符集还是多字节集),两种方案,一种修改字符集为多字节集,二是将字符串前面加 _T("").
  error C2664: “LoadLibraryW”: 不能将参数 1 从“const char *”转换为“LPCWSTR”

在使用VS2010编写运行时动态链接dll文件时出现的一个问题,问题解决得益于此文章:http://blog.sina.com.cn/s/blog_6a2236590100xbgl.html
通过调用这个函数:
LoadLibrary出现的该问题。
原因 :工程只支持UNICODE字符
解决方法:
1、在解决方案资源管理器中的工程上右键属性->配置属性-->常规--->字符集---->使用多字节符字符集
2、也就是宽字符,所以下面这行代码,应该编译有错误
hinst=LoadLibrary("InTheHand.Net.Personal.dll");
也就是:
cannot convert parameter 1 from 'char [27]' to 'const unsigned short *'
改为:
hinst=LoadLibrary(L"InTheHand.Net.Personal.dll");
或者
hinst=LoadLibrary(_T("InTheHand.Net.Personal.dll"));

 感谢:http://blog.sina.com.cn/s/blog_6a2236590100xbgl.html ; https://www.cnblogs.com/holyprince/p/4236586.html

原文地址:https://www.cnblogs.com/carle-09/p/11098231.html