如何将DLL链接到我的主项目? (获得未解决的外部错误)

时间:2015-10-29 22:44:14

标签: c++ dll c++builder dynamic-linking c++builder-xe7

我还在学习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()功能。

我也尝试过的东西: - &gt;在项目中添加.lib,.h,.dll文件;

- &gt;在控制台应用程序文件夹的同一文件夹中添加.lib,.h,.dll文件;

- &gt;在项目的引用中添加了.lib,.h,.dll文件(C ++共享选项)。

我的想法:当我在编写主程序代码时找到函数/类时,编译器正在读取MathFuncsDLL.h。

我现在一直遇到的问题:

  

[ilink32错误]错误:未解析的外部&#39; MathFuncs :: MyMathFuncs :: Add(double,double)&#39;从C:\ USERS \ MAURO \ DESKTOP \ PROJETO \ WIN32 \ DEBUG \ FILE1.OBJ引用

     

[ilink32错误]错误:未解析的外部&#39; MathFuncs :: MyMathFuncs :: Subtract(double,double)&#39;从C:\ USERS \ MAURO \ DESKTOP \ PROJETO \ WIN32 \ DEBUG \ FILE1.OBJ引用

     

[ilink32错误]错误:未解析的外部&#39; MathFuncs :: MyMathFuncs :: Multiply(double,double)&#39;从C:\ USERS \ MAURO \ DESKTOP \ PROJETO \ WIN32 \ DEBUG \ FILE1.OBJ引用

     

[ilink32错误]错误:未解析的外部&#39; MathFuncs :: MyMathFuncs :: Divide(double,double)&#39;从C:\ USERS \ MAURO \ DESKTOP \ PROJETO \ WIN32 \ DEBUG \ FILE1.OBJ引用

编译器的详细信息: - &GT; C ++ builder XE7。

从现在开始,非常感谢。

1 个答案:

答案 0 :(得分:1)

你使用LoadLibrary()是错误的,没用。您没有将返回的模块句柄传递给GetProcAddress()以动态加载DLL函数。因此,请移除对LoadLibrary()的调用。

您的控制台代码正在尝试静态链接到DLL函数。要解析引用,您需要在项目管理器中或通过代码中的.lib语句将DLL的#pragma comment(lib, Project1.lib)文件添加到控制台项目中。仅.lib文件存在于控制台项目的文件夹中是不够的。

话虽这么说,你的DLL不应该尝试导出命名空间类的静态函数。改为导出扁平C风格的独立功能。您的标题可以提供用于C ++的命名空间包装类,只是不要导出它。

在DLL边界上抛出异常(尤其是基于类的异常)也是不安全的。你需要完全摆脱它。对于Divide(),要么让调用者验证它永远不会通过b=0,要么更改Divide()的签名以返回bool表示成功/失败并使用一个单独的输出参数,用于返回除法结果。

尝试更像这样的事情:

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;
}