Visual C++:从 DLL 调用时 XGBoost 不起作用

Posted

技术标签:

【中文标题】Visual C++:从 DLL 调用时 XGBoost 不起作用【英文标题】:Visual C++ : XGBoost does not work when called from a DLL 【发布时间】:2018-08-06 22:31:15 【问题描述】:

我需要在 Visual C++ 项目 DLL 中使用 XGBoost。 我已经能够使用 VC++ 和 CMake 下载和构建 XGBoost 源代码。

当我在测试控制台应用程序中包含 XGBoost 代码时,它工作正常。

但是,当我尝试在 DLL 项目中复制我对控制台应用程序所做的操作时,它不会编译。 我什至很难在项目中使用基本的 XGBoost 类型。

我怀疑问题在于我对 DLL 项目的无知,希望您能提供帮助。

以下是我的 DLL 项目中发生的情况: 当我使用以下包含作为 cpp 类文件的第一行时,它会编译:#include <xgboost\c_api.h>

编译后,如果我尝试使用此包含文件中定义的简单类型,则构建失败并显示以下消息: ...\dll_test\xgb_driver.cpp(20):错误 C2065:“BoosterHandle”:未声明的标识符

这是导致错误的行:BoosterHandle my_handle;

“BoosterHandle”实际上是在<xgboost\c_api.h>中定义的

当我将包含置于任何其他包含之下时,我收到以下错误消息: 1>c:\tools\src\xgboost\include\xgboost\c_api.h(29):错误 C4430:缺少类型说明符 - 假定为 int。注意:C++ 不支持 default-int

1>c:\tools\src\xgboost\include\xgboost\c_api.h(29): 错误 C2146: 语法错误: 缺少 ';'在标识符“bst_ulong”之前

下面是关于我如何让 XGBoost 与控制台应用程序一起工作以及我如何创建 DLL 项目的更多信息。

=-=-=-=-=-=

这是我在控制台中使用 XGBoost 时所做的。关于它的一切似乎都有效。我已经测试了模型预测,它们是 与我在 R 中看到的一致。

使用此处找到的文档: https://xgboost.readthedocs.io/en/latest/build.html

    我下载了 XGBoost 源代码并使用 CMake 和 Visual Studio 2015 构建它。

    在项目 > 链接器 > 输入 > 附加依赖项下, 我添加了 xgboost.lib 文件

    在项目下 > 链接器 > 常规 > 附加库目录 我添加了对 ...\xgboost\build\Release

    的引用

    在项目下 > VC++ 目录 > 包含目录 我将路径添加到 ...\xgboost\rabit\include 和 ...\xgboost\include

    我把xgboost.dll放在生成.exe的目录下。

从这里开始,一帆风顺。

=-=-=-=-=-=

这是我为创建 Visual C++ DLL 项目所做的工作:

选择文件 > 新建 > 项目后,我选择了一个 ATL DLL 项目(这是项目要求的一部分)。

对于项目中包含的 XGBoost,我重复了上面的步骤 1-5,但将 xgboost.dll 文件放在了 将生成项目 DLL。

这是我创建的简单类的头文件的来源:

#pragma once
class XGB_Driver

public:
    XGB_Driver();
    ~XGB_Driver();

    float callXGB(float sample_input);
;

这里是简单 cpp 文件的来源:

#include <xgboost/c_api.h>
#include "stdafx.h"
#include "XGB_Driver.h"


XGB_Driver::XGB_Driver()



XGB_Driver::~XGB_Driver()



float XGB_Driver::callXGB(float simple_input) 
    BoosterHandle my_handle;
    return(0);

为什么这对 ATL DLL 项目不起作用,但对控制台应用程序却起作用,这真的让我头疼不已。

非常感谢您的帮助。

最好, 戴夫

【问题讨论】:

如果你#include &lt;cstdint&gt; 之前 #include &lt;xgboost/c_api.h&gt;会发生什么?或者更好,如果您将#include "stdafx.h" 移到#includes 列表的顶部? CristiFati,在 xgboost 标头之前添加的#include 似乎已经解决了这个问题。我不确定为什么在 DLL 项目中需要它,但不是控制台项目,但是,嘿,我会接受的。我想感谢您的回答,但我的选择是添加评论或回答我自己的问题。非常感谢您的帮助。 移动顶部的#include "stdafx.h" 怎么样?如果仅此一项不起作用,则应将 #include &lt;cstdint&gt; 放在 StdAfx.h 中。这就是应该这样做的方式。让我知道它是否适合您,然后我会发布一个带有解释和所有内容的答案。 它有效,如果你能详细说明它为什么有效,我将不胜感激。 另一方面,我不理解问题第一部分中的错误,此时构建 xgboost 对我来说开销太大。所以,继续回答你自己的问题。 【参考方案1】:

在 CristiFati 的帮助下,我相信这个问题已经得到解答。 无论出于何种原因,在 DLL 项目中使用带有 C++ 的 XGBoost 似乎需要额外的包含,超出在控制台应用程序中使用它所需的内容。 我目前正在构建 DLL 项目,并添加了:#include &lt;cstdint&gt;

【讨论】:

以上是关于Visual C++:从 DLL 调用时 XGBoost 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

在 C++ 中调用 Visual Basic DLL

在 Visual Studio 6 中从 VB 调用 VS2010 C++ dll

Visual Lisp:如何调用外部 C++ DLL 中的函数

调试由 C# Visual Studio 2010 插件导入的 C++ dll

Visual C++ - 覆盖从 DLL 导入的函数?

菜鸟进阶之:VC++之Visual Studio中DLL调用实现[静态嵌入]