如何 link 一个 DLL 到我的主项目? (获取未解决的外部错误)
How to link a DLL to my main project? (Getting unresolved external error)
我仍在学习 C++ 语言的一些用法。
因此,我决定创建我的库(动态)并将其导入到我的项目中。
我已经按照互联网上教程的一些步骤进行操作,但我总是遇到未解决的外部错误...
让我去DLL项目:
File1.cpp:
#include "MathFuncsDll.h"
#include <stdexcept>
using namespace std;
namespace MathFuncs
{
double MyMathFuncs::Add(double a, double b)
{
return a + b;
}
double MyMathFuncs::Subtract(double a, double b)
{
return a - b;
}
double MyMathFuncs::Multiply(double a, double b)
{
return a * b;
}
double MyMathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw invalid_argument("b cannot be zero!");
}
return a / b;
}
}
MathFuncs.h:
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif
namespace MathFuncs
{
// This class is exported from the MathFuncsDll.dll
class MyMathFuncs
{
public:
// Returns a + b
static MATHFUNCSDLL_API double Add(double a, double b);
// Returns a - b
static MATHFUNCSDLL_API double Subtract(double a, double b);
// Returns a * b
static MATHFUNCSDLL_API double Multiply(double a, double b);
// Returns a / b
// Throws const std::invalid_argument& if b is 0
static MATHFUNCSDLL_API double Divide(double a, double b);
};
}
结果:编译成功(获得Project1.dll和Project1.lib个文件)。
使用以下详细信息启动了一个新的控制台应用程序:
File1.cpp:
// MyExecRefsDll.cpp
// compile with: /EHsc /link MathFuncsDll.lib
#include <iostream>
#include <Windows.h>
#include "MathFuncsDll.h"
using namespace std;
int main()
{
double a = 7.4;
int b = 99;
try {
LoadLibrary(TEXT("MathFuncsDll.dll")); // Also tried without TEXT();
cout << "a + b = " <<
MathFuncs::MyMathFuncs::Add(a, b) << endl;
cout << "a - b = " <<
MathFuncs::MyMathFuncs::Subtract(a, b) << endl;
cout << "a * b = " <<
MathFuncs::MyMathFuncs::Multiply(a, b) << endl;
cout << "a / b = " <<
MathFuncs::MyMathFuncs::Divide(a, b) << endl;
try
{
cout << "a / 0 = " <<
MathFuncs::MyMathFuncs::Divide(a, 0) << endl;
}
catch (const invalid_argument &e)
{
cout << "Caught exception: " << e.what() << endl;
}
}
catch (...){
cout << "Problem when loading dll file" << endl;
}
system("pause");
return 0;
}
PS.:
我也试过没有 LoadLibrary()
功能。
我也试过的东西:
->在项目中添加了.lib、.h、.dll文件;
->添加了.lib, .h, .dll 文件在控制台应用程序文件夹的同一个文件夹中;
->在项目的引用中添加了.lib、.h、.dll文件(C++共享选项)。
我的想法: MathFuncsDLL.h 正在被编译器读取,一旦我在编写主程序代码时找到 functions/classes
我目前遇到的问题:
[ilink32 Error] Error: Unresolved external 'MathFuncs::MyMathFuncs::Add(double, double)' referenced from C:\USERS\MAURO\DESKTOP\PROJETO\WIN32\DEBUG\FILE1.OBJ
[ilink32 Error] Error: Unresolved external 'MathFuncs::MyMathFuncs::Subtract(double, double)' referenced from C:\USERS\MAURO\DESKTOP\PROJETO\WIN32\DEBUG\FILE1.OBJ
[ilink32 Error] Error: Unresolved external 'MathFuncs::MyMathFuncs::Multiply(double, double)' referenced from C:\USERS\MAURO\DESKTOP\PROJETO\WIN32\DEBUG\FILE1.OBJ
[ilink32 Error] Error: Unresolved external 'MathFuncs::MyMathFuncs::Divide(double, double)' referenced from C:\USERS\MAURO\DESKTOP\PROJETO\WIN32\DEBUG\FILE1.OBJ
编译器详情:
-> C++ 生成器 XE7。
从现在开始,非常感谢。
你使用LoadLibrary()
是错误的,没有用的。您没有将 returned 模块句柄传递给 GetProcAddress()
以动态加载 DLL 函数。所以删除对 LoadLibrary()
.
的调用
您的控制台代码正在尝试 link 静态地访问 DLL 函数。要解析引用,您需要将 DLL 的 .lib
文件添加到您的控制台项目,可以在项目管理器中添加,也可以通过代码中的 #pragma comment(lib, Project1.lib)
语句添加。 .lib 文件仅存在于控制台项目的文件夹中是不够的。
话虽这么说,您的 DLL 不应该尝试导出命名空间 class 静态函数。改为导出平面 C-style 独立函数。您的 header 可以提供命名空间包装器 class 以供在 C++ 中使用,只是不要导出它。
在 DLL 边界上抛出异常(尤其是 class-based 异常)也不安全。你需要完全摆脱它。在 Divide()
的情况下,要么让调用者验证它从未通过 b=0
,要么将 Divide()
的签名更改为 return 一个 bool
指示 success/failure 并使用单独的输出参数 return 除法结果。
试试像这样的东西:
MathFuncsDll.cpp:
#define MATHFUNCSDLL_EXPORTS
#include "MathFuncsDll.h"
double MathFuncs_Add(double a, double b)
{
return a + b;
}
double MathFuncs_Subtract(double a, double b)
{
return a - b;
}
double MathFuncs_Multiply(double a, double b)
{
return a * b;
}
double MathFuncs_Divide(double a, double b)
{
return a / b;
}
/* alternatively:
bool MathFuncs_Divide(double a, double b, double *result)
{
if (b == 0) return false;
if (result) *result = a / b;
return true;
}
*/
MathFuncsDll.h:
#ifndef MathFuncsDllH
#define MathFuncsDllH
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Returns a + b
MATHFUNCSDLL_API double MathFuncs_Add(double a, double b);
// Returns a - b
MATHFUNCSDLL_API double MathFuncs_Subtract(double a, double b);
// Returns a * b
MATHFUNCSDLL_API double MathFuncs_Multiply(double a, double b);
// Returns a / b
MATHFUNCSDLL_API double MathFuncs_Divide(double a, double b);
// alternatively: bool MathFuncs_Divide(double a, double b, double *result);
#ifdef __cplusplus
}
#include <stdexcept>
namespace MathFuncs
{
class MyMathFuncs
{
public:
static Add(double a, double b) { return MathFuncs_Add(a, b); }
static double Subtract(double a, double b) { return MathFuncs_Subtract(a, b); }
static double Multiply(double a, double b) { return MathFuncs_Multiply(a, b); }
static double Divide(double a, double b)
{
if (b == 0)
throw std::invalid_argument("b cannot be zero!");
return MathFuncs_Divide(a, b);
/* alternatively:
double result;
if (!MathFuncs_Divide(a, b, &result))
throw std::invalid_argument("b cannot be zero!");
return result;
*/
}
};
}
#endif
#endif
File1.cpp:
#include <windows.h>
#include <iostream>
// if you don't add the DLL .lib file to the project using the Project Manager,
// uncomment this statement ... either way, you really should rename your DLL
// project to something more meaningful then "Project1" ...
// #pragma comment(lib, "Project1.lib")
#include "MathFuncsDll.h"
int main()
{
double a = 7.4;
int b = 99;
try
{
std::cout << "a + b = " << MathFuncs::MyMathFuncs::Add(a, b) << std::endl;
std::cout << "a - b = " << MathFuncs::MyMathFuncs::Subtract(a, b) << std::endl;
std::cout << "a * b = " << MathFuncs::MyMathFuncs::Multiply(a, b) << std::endl;
std::cout << "a / b = " << MathFuncs::MyMathFuncs::Divide(a, b) << std::endl;
try
{
std::cout << "a / 0 = " << MathFuncs::MyMathFuncs::Divide(a, 0) << std::endl;
}
catch (const std::invalid_argument &e)
{
std::cout << "Caught exception: " << e.what() << std::endl;
}
}
catch (...)
{
std::cout << "Problem when loading dll file" << std::endl;
}
system("pause");
return 0;
}
我仍在学习 C++ 语言的一些用法。
因此,我决定创建我的库(动态)并将其导入到我的项目中。 我已经按照互联网上教程的一些步骤进行操作,但我总是遇到未解决的外部错误...
让我去DLL项目:
File1.cpp:
#include "MathFuncsDll.h"
#include <stdexcept>
using namespace std;
namespace MathFuncs
{
double MyMathFuncs::Add(double a, double b)
{
return a + b;
}
double MyMathFuncs::Subtract(double a, double b)
{
return a - b;
}
double MyMathFuncs::Multiply(double a, double b)
{
return a * b;
}
double MyMathFuncs::Divide(double a, double b)
{
if (b == 0)
{
throw invalid_argument("b cannot be zero!");
}
return a / b;
}
}
MathFuncs.h:
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif
namespace MathFuncs
{
// This class is exported from the MathFuncsDll.dll
class MyMathFuncs
{
public:
// Returns a + b
static MATHFUNCSDLL_API double Add(double a, double b);
// Returns a - b
static MATHFUNCSDLL_API double Subtract(double a, double b);
// Returns a * b
static MATHFUNCSDLL_API double Multiply(double a, double b);
// Returns a / b
// Throws const std::invalid_argument& if b is 0
static MATHFUNCSDLL_API double Divide(double a, double b);
};
}
结果:编译成功(获得Project1.dll和Project1.lib个文件)。
使用以下详细信息启动了一个新的控制台应用程序:
File1.cpp:
// MyExecRefsDll.cpp
// compile with: /EHsc /link MathFuncsDll.lib
#include <iostream>
#include <Windows.h>
#include "MathFuncsDll.h"
using namespace std;
int main()
{
double a = 7.4;
int b = 99;
try {
LoadLibrary(TEXT("MathFuncsDll.dll")); // Also tried without TEXT();
cout << "a + b = " <<
MathFuncs::MyMathFuncs::Add(a, b) << endl;
cout << "a - b = " <<
MathFuncs::MyMathFuncs::Subtract(a, b) << endl;
cout << "a * b = " <<
MathFuncs::MyMathFuncs::Multiply(a, b) << endl;
cout << "a / b = " <<
MathFuncs::MyMathFuncs::Divide(a, b) << endl;
try
{
cout << "a / 0 = " <<
MathFuncs::MyMathFuncs::Divide(a, 0) << endl;
}
catch (const invalid_argument &e)
{
cout << "Caught exception: " << e.what() << endl;
}
}
catch (...){
cout << "Problem when loading dll file" << endl;
}
system("pause");
return 0;
}
PS.:
我也试过没有 LoadLibrary()
功能。
我也试过的东西: ->在项目中添加了.lib、.h、.dll文件;
->添加了.lib, .h, .dll 文件在控制台应用程序文件夹的同一个文件夹中;
->在项目的引用中添加了.lib、.h、.dll文件(C++共享选项)。
我的想法: MathFuncsDLL.h 正在被编译器读取,一旦我在编写主程序代码时找到 functions/classes
我目前遇到的问题:
[ilink32 Error] Error: Unresolved external 'MathFuncs::MyMathFuncs::Add(double, double)' referenced from C:\USERS\MAURO\DESKTOP\PROJETO\WIN32\DEBUG\FILE1.OBJ
[ilink32 Error] Error: Unresolved external 'MathFuncs::MyMathFuncs::Subtract(double, double)' referenced from C:\USERS\MAURO\DESKTOP\PROJETO\WIN32\DEBUG\FILE1.OBJ
[ilink32 Error] Error: Unresolved external 'MathFuncs::MyMathFuncs::Multiply(double, double)' referenced from C:\USERS\MAURO\DESKTOP\PROJETO\WIN32\DEBUG\FILE1.OBJ
[ilink32 Error] Error: Unresolved external 'MathFuncs::MyMathFuncs::Divide(double, double)' referenced from C:\USERS\MAURO\DESKTOP\PROJETO\WIN32\DEBUG\FILE1.OBJ
编译器详情: -> C++ 生成器 XE7。
从现在开始,非常感谢。
你使用LoadLibrary()
是错误的,没有用的。您没有将 returned 模块句柄传递给 GetProcAddress()
以动态加载 DLL 函数。所以删除对 LoadLibrary()
.
您的控制台代码正在尝试 link 静态地访问 DLL 函数。要解析引用,您需要将 DLL 的 .lib
文件添加到您的控制台项目,可以在项目管理器中添加,也可以通过代码中的 #pragma comment(lib, Project1.lib)
语句添加。 .lib 文件仅存在于控制台项目的文件夹中是不够的。
话虽这么说,您的 DLL 不应该尝试导出命名空间 class 静态函数。改为导出平面 C-style 独立函数。您的 header 可以提供命名空间包装器 class 以供在 C++ 中使用,只是不要导出它。
在 DLL 边界上抛出异常(尤其是 class-based 异常)也不安全。你需要完全摆脱它。在 Divide()
的情况下,要么让调用者验证它从未通过 b=0
,要么将 Divide()
的签名更改为 return 一个 bool
指示 success/failure 并使用单独的输出参数 return 除法结果。
试试像这样的东西:
MathFuncsDll.cpp:
#define MATHFUNCSDLL_EXPORTS
#include "MathFuncsDll.h"
double MathFuncs_Add(double a, double b)
{
return a + b;
}
double MathFuncs_Subtract(double a, double b)
{
return a - b;
}
double MathFuncs_Multiply(double a, double b)
{
return a * b;
}
double MathFuncs_Divide(double a, double b)
{
return a / b;
}
/* alternatively:
bool MathFuncs_Divide(double a, double b, double *result)
{
if (b == 0) return false;
if (result) *result = a / b;
return true;
}
*/
MathFuncsDll.h:
#ifndef MathFuncsDllH
#define MathFuncsDllH
#ifdef MATHFUNCSDLL_EXPORTS
#define MATHFUNCSDLL_API __declspec(dllexport)
#else
#define MATHFUNCSDLL_API __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
// Returns a + b
MATHFUNCSDLL_API double MathFuncs_Add(double a, double b);
// Returns a - b
MATHFUNCSDLL_API double MathFuncs_Subtract(double a, double b);
// Returns a * b
MATHFUNCSDLL_API double MathFuncs_Multiply(double a, double b);
// Returns a / b
MATHFUNCSDLL_API double MathFuncs_Divide(double a, double b);
// alternatively: bool MathFuncs_Divide(double a, double b, double *result);
#ifdef __cplusplus
}
#include <stdexcept>
namespace MathFuncs
{
class MyMathFuncs
{
public:
static Add(double a, double b) { return MathFuncs_Add(a, b); }
static double Subtract(double a, double b) { return MathFuncs_Subtract(a, b); }
static double Multiply(double a, double b) { return MathFuncs_Multiply(a, b); }
static double Divide(double a, double b)
{
if (b == 0)
throw std::invalid_argument("b cannot be zero!");
return MathFuncs_Divide(a, b);
/* alternatively:
double result;
if (!MathFuncs_Divide(a, b, &result))
throw std::invalid_argument("b cannot be zero!");
return result;
*/
}
};
}
#endif
#endif
File1.cpp:
#include <windows.h>
#include <iostream>
// if you don't add the DLL .lib file to the project using the Project Manager,
// uncomment this statement ... either way, you really should rename your DLL
// project to something more meaningful then "Project1" ...
// #pragma comment(lib, "Project1.lib")
#include "MathFuncsDll.h"
int main()
{
double a = 7.4;
int b = 99;
try
{
std::cout << "a + b = " << MathFuncs::MyMathFuncs::Add(a, b) << std::endl;
std::cout << "a - b = " << MathFuncs::MyMathFuncs::Subtract(a, b) << std::endl;
std::cout << "a * b = " << MathFuncs::MyMathFuncs::Multiply(a, b) << std::endl;
std::cout << "a / b = " << MathFuncs::MyMathFuncs::Divide(a, b) << std::endl;
try
{
std::cout << "a / 0 = " << MathFuncs::MyMathFuncs::Divide(a, 0) << std::endl;
}
catch (const std::invalid_argument &e)
{
std::cout << "Caught exception: " << e.what() << std::endl;
}
}
catch (...)
{
std::cout << "Problem when loading dll file" << std::endl;
}
system("pause");
return 0;
}