目录
Step#1 创建MFC应用程序,名称TestDll,基于对话框的,最后点击Finish
第一个错误 error C2664 cannot convert argument 1 from 'const char [7]' to 'const wchar_t *'
第二个错误 error MSB8031: Building an MFC project for a non-Unicode character set is deprecated.
第三个错误 error LNK2019: unresolved external symbol
第四个错误error LNK1104: cannot open file 'MyDll0.lib'
第五个错误 error LNK2019: unresolved external symbol __imp__add referenced in function
第六个错误 找不到MyDll0.dll,无法继续执行代码。重新安装程序可能会解决此问题
Step#4添加代码之第二种方法【推荐使用此种,实际工程中应用的比较多】
错误及解决办法error LNK2019: unresolved external symbol _add referenced in function
Step#1. 新建C#项目,Windows Forms Application,取名CSharpTestDll
Step#3双击Add按钮添加事件响应函数,Subtract按钮也要双击
Step#4. 将被使用到的MyDll0.dll放置在"项目的Output Path"目录下。
MFC应用程序使用DLL
Step#1 创建MFC应用程序,名称TestDll,基于对话框的,最后点击Finish
Step#2 添加两个按钮Add和Subtract
这里使用的dll为《创建动态链接库(dll)》中创建的MyDll0.dll
ID | Caption | 命令响应函数 | 函数功能 |
IDC_BTN_ADD | Add | OnBnClickedBtnAdd | 调用MyDll0.dll的add函数 |
IDC_BTN_SUBTRACT | Subtract | OnBnClickedBtnSubtract | 调用MyDll0.dll的subtract函数 |
Step#3双击Add按钮添加命令响应函数
Step#4添加代码
extern "C" _declspec(dllimport) int _stdcall add(int a, int b);
extern "C" _declspec(dllimport) int _stdcall subtract(int a, int b);
void CTestDllDlg::OnBnClickedBtnAdd()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("5+3=%d", add(5, 3));
MessageBox(str);
}
void CTestDllDlg::OnBnClickedBtnSubtract()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("5-3=%d", subtract(5, 3));
MessageBox(str);
}
Step#5错误及解决办法
第一个错误 error C2664 cannot convert argument 1 from 'const char [7]' to 'const wchar_t *'
错误说明:error C2664: 'void ATL::CStringT<wchar_t,StrTraitMFC_DLL<wchar_t,ATL::ChTraitsCRT<wchar_t>>>::Format(UINT,...)' : cannot convert argument 1 from 'const char [7]' to 'const wchar_t *'
1> Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
解决办法:VS2013默认使用UNICODE编码,将其修改为Not Set
Project -> Properties -> Configuration Properties -> General -> Character Set: Not Set
第二个错误 error MSB8031: Building an MFC project for a non-Unicode character set is deprecated.
错误说明:error MSB8031: Building an MFC project for a non-Unicode character set is deprecated. You must change the project property to Unicode or download an additional library. See http://go.microsoft.com/fwlink/p/?LinkId=286820 for more information.
解决办法:
VS2013把 multi-byte character set 支持移除了
去微软网站下载这个组件就行了,网址http://go.microsoft.com/fwlink/p/?LinkId=286820
Multibyte MFC Library for Visual Studio 2013
【注意】根据自己的VS版本来选择组件,笔者的是VS2013
参考文章https://blog.csdn.net/tahelin/article/details/30312881
第三个错误 error LNK2019: unresolved external symbol
错误说明:error LNK2019: unresolved external symbol __imp__add@8 referenced in function "public: void __thiscall CTestDllDlg::OnBnClickedBtnAdd(void)" (?OnBnClickedBtnAdd@CTestDllDlg@@QAEXXZ)
error LNK2019: unresolved external symbol "int __cdecl add(int,int)" (?add@@YAHHH@Z) referenced in function "public: void __thiscall CTestDllDlg::OnBnClickedBtnAdd(void)" (?OnBnClickedBtnAdd@CTestDllDlg@@QAEXXZ)
error LNK2019: unresolved external symbol "int __cdecl subtract(int,int)" (?subtract@@YAHHH@Z) referenced in function "public: void __thiscall CTestDllDlg::OnBnClickedBtnSubtract(void)" (?OnBnClickedBtnSubtract@CTestDllDlg@@QAEXXZ)
error LNK1120: 2 unresolved externals
解决办法:这几个错误是链接(Link)时发生的,因为链接器需要知道这两个函数在哪个地方实现的,所以报错。
1. 将MyDll0.lib放置在TestDll.exe生成目录中,笔者的项目中为Debug目录,如下图
2. 按照下图添加Additional Dependecies附加依赖项
第四个错误error LNK1104: cannot open file 'MyDll0.lib'
解决办法:
这是因为没有告诉链接器(LINK)去哪里找这个MyDll0.lib
VC++ Directories -> Library Directories(附加库目录)
填入MyDll0.lib所在的目录
绝对路径F:\Code\VS_C++\TestDll\Debug
相对路径..\Debug【两个点代表上层目录】
在笔者的项目中,当前目录是TestDll.sln所在的目录
至此已经可以Build&Link成功,并生成了TestDll.exe,如下图:
第五个错误 error LNK2019: unresolved external symbol __imp__add referenced in function
错误说明:error LNK2019: unresolved external symbol __imp__add referenced in function "public: void __thiscall CTestDllDlg::OnBnClickedBtnAdd(void)" (?OnBnClickedBtnAdd@CTestDllDlg@@QAEXXZ)
【重点】解决办法:要看导出函数声明与导入函数声明是否一致
本例中,查看MyDll0.h中的函数声明是否与使用者TestDllDlg.cpp中的函数声明是否一致
错误例子:
MyDll0.h中的声明为
extern "C" _declspec(dllexport) int _stdcall add(int a, int b);
TestDllDlg.cpp中的声明为
extern "C" _declspec(dllimport) int add(int a, int b);【缺少_stdcall,所以错误】
正确例子:
MyDll0.h中的声明为
extern "C" _declspec(dllexport) int _stdcall add(int a, int b);
TestDllDlg.cpp中的声明为
extern "C" _declspec(dllimport) int _stdcall add(int a, int b);
第六个错误 找不到MyDll0.dll,无法继续执行代码。重新安装程序可能会解决此问题
解决办法:将MyDll0.dll放置在TestDll.exe的同层目录下(最终打包给别人的就是这样的目录结构),如下图:
Step#6程序运行结果
Step#4添加代码之第二种方法【推荐使用此种,实际工程中应用的比较多】
TestDllDlg.cpp代码
只需要加上一句#include "MyDll0.h"
#include "MyDll0.h"
void CTestDllDlg::OnBnClickedBtnAdd()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("5+3=%d", add(5, 3));
MessageBox(str);
}
void CTestDllDlg::OnBnClickedBtnSubtract()
{
// TODO: Add your control notification handler code here
CString str;
str.Format("5-3=%d", subtract(5, 3));
MessageBox(str);
}
MyDll0.h代码
具体可以参考《创建动态链接库(dll)》
#pragma once
#ifndef _MYDLL_API
#define _MYDLL_API extern "C" _declspec(dllexport)
#else
#define _MYDLL_API _declspec(dllimport)
#endif
_MYDLL_API int _stdcall add(int a, int b);
_MYDLL_API int _stdcall subtract(int a, int b);
错误及解决办法error LNK2019: unresolved external symbol _add referenced in function
错误说明:error LNK2019: unresolved external symbol _add referenced in function "public: void __thiscall CTestDllDlg::OnBnClickedBtnAdd(void)" (?OnBnClickedBtnAdd@CTestDllDlg@@QAEXXZ)
解决办法:先把用到的头文件复制到调用者的目录下,然后配置包含目录
1. 复制MyDll0.h到TestDll.h/TestDll.cpp, TestDllDlg.h/TestDllDlg.cpp同层目录下
2. 配置包含目录:VC++ Directories -> Include Directories(包含目录)
不会用相对路径的朋友就填绝对路径:F:\Code\VS_C++\TestDll\TestDll
相对路径..\TestDll【两个点代表上层目录】
在笔者的项目中,当前目录是TestDll.sln所在的目录
汇总C/C++使用 DLL步骤
1. 导入函数声明
Dll的使用者(调用者、客户端)需要将导入函数声明为extern或_declspec(dllimport)
并配置包含目录:VC++ Directories -> Include Directories(包含目录)【头文件目录】
【建议使用相对路径】
2. 添加库文件:
将MyDll.lib放置在TestDll.exe的同层目录下【建议使用相对路径】
并配置附加库目录:VC++ Directories -> Library Directories(附加库目录)
3. 将被用到的.dll放置在使用者(.exe)能找到的目录下
可以参考文章《动态链接库加载的两种方式》中的“四大路径及顺序”
【注意事项】如果xxx.dll有任何更新(xxx.h/xxx.cpp),需要将更新&build后的xxx.h/xxx.lib/xxx.dll提供给使用者(客户端)。
C#应用程序使用DLL
与C/C++使用DLL相比要方便多。
Step#1. 新建C#项目,Windows Forms Application,取名CSharpTestDll
Step#2 添加两个按钮Add和Subtract
![](https://i-blog.csdnimg.cn/blog_migrate/618dd78195d51b4db844b4024de4ae74.png)
Step#3双击Add按钮添加事件响应函数,Subtract按钮也要双击
Step#4. 将被使用到的MyDll0.dll放置在"项目的Output Path"目录下。
建议去使用者(客户端)项目属性中去查看,保持一致才不会出错。
【注意】需要查看这几个红色框出的位置,如下图
项目的Output Path(输出目录)
项目名称 -> 右击 -> 属性Properties
Step#5添加代码
1. 在Form1.cs中添加一行代码
using System.Runtime.InteropServices; //DLL support
2. 在添加如下代码来声明add与subtract函数是外部函数
一般格式如下
[DLLImport(“DLL文件路径”)]
修饰符 extern 返回值类型 方法名称(参数列表)
DLLImport会按照顺序去查找DLL文件(程序当前目录>System32目录>环境变量Path所设置路径)。
【注意】
1.将被用到的.dll放置在使用者(.exe)能找到的目录下
可以参考文章《动态链接库加载的两种方式》中的“四大路径及顺序”
2. 导出几个函数,就要写几个[DLLImport(“DLL文件路径”)]
[DllImport("MyDll0.dll")] // 注意.dll路径要能被找到
public static extern int add(int a, int b); // 被调用的函数需要被声明为static与extern
[DllImport("MyDll0.dll")] // 注意.dll路径要能被找到
public static extern int subtract(int a, int b); // 被调用的函数需要被声明为static与extern
3. 在btn_add_Click与btn_Subtract_Click函数中添加如下代码
private void btn_add_Click(object sender, EventArgs e)
{
string str = "3 + 5 = " + add(3, 5).ToString();
MessageBox.Show(str, "提示");
}
private void btn_Subtract_Click(object sender, EventArgs e)
{
string str = "3 - 5 = " + subtract(3, 5).ToString();
MessageBox.Show(str, "提示");
}
Form1.cs完整版代码如下
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Runtime.InteropServices; //DLL support
namespace CSharpTestDll
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
[DllImport("MyDll0.dll")] // 注意.dll路径要能被找到
public static extern int add(int a, int b); // 被调用的函数需要被声明为static与extern
[DllImport("MyDll0.dll")] // 注意.dll路径要能被找到
public static extern int subtract(int a, int b); // 被调用的函数需要被声明为static与extern
private void btn_add_Click(object sender, EventArgs e)
{
string str = "3 + 5 = " + add(3, 5).ToString();
MessageBox.Show(str, "提示");
}
private void btn_subtract_Click(object sender, EventArgs e)
{
string str = "3 + 5 = " + subtract(3, 5).ToString();
MessageBox.Show(str, "提示");
}
}
}
Step#6错误及解决办法
常见错误:无法加载“MyDll0.dll”:找不到指定的模块
解决办法:将被使用到的MyDll0.dll放置在.exe同层目录下。
Step#7 Build成功&运行
辅助工具
Dumpbin
dumpbin -exports MyDll0.dll【推荐使用,速度快】
Dependency Walker
下载地址http://www.dependencywalker.com/
更多实用工具请参考《软件开发者的常用工具》
更多内容请看C/C++动态链接库(DLL)详解
来源:孙鑫_VC++_学习笔记