Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/145.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++;DLL不导出函数 我开发了一个C++库,作为VisualStudio 2013(C++ 11)中的DLL导出,并且我遇到了一个挑战,库一旦被另一个程序导入为外部依赖项,就包含了我想要的类,但没有包含类的函数。_C++_C++11_Visual C++_Dll_Dllexport - Fatal编程技术网

C++;DLL不导出函数 我开发了一个C++库,作为VisualStudio 2013(C++ 11)中的DLL导出,并且我遇到了一个挑战,库一旦被另一个程序导入为外部依赖项,就包含了我想要的类,但没有包含类的函数。

C++;DLL不导出函数 我开发了一个C++库,作为VisualStudio 2013(C++ 11)中的DLL导出,并且我遇到了一个挑战,库一旦被另一个程序导入为外部依赖项,就包含了我想要的类,但没有包含类的函数。,c++,c++11,visual-c++,dll,dllexport,C++,C++11,Visual C++,Dll,Dllexport,我已经包括了一个特定的类,它应该是这个DLL导出的一部分 这是我的RegressionTrainer类头文件: #ifndef REGRESSION_TRAINER_H #define REGRESSION_TRAINER_H #include "MachineLearning.h" #pragma once #ifndef DLL_EXPORT #define DLL_EXPORT __declspec(dllexport) #endif using namespace MachineLe

我已经包括了一个特定的类,它应该是这个DLL导出的一部分

这是我的RegressionTrainer类头文件:

#ifndef REGRESSION_TRAINER_H
#define REGRESSION_TRAINER_H
#include "MachineLearning.h"
#pragma once

#ifndef DLL_EXPORT
#define DLL_EXPORT __declspec(dllexport)
#endif

using namespace MachineLearning;

namespace MachineLearningTraining{

public class RegressionTrainer{
public:
    DLL_EXPORT RegressionTrainer();
    virtual DLL_EXPORT ~RegressionTrainer();

    std::vector<sample_type> DLL_EXPORT getInputData();
    std::vector<double> DLL_EXPORT getAugmentedOutputs();
    std::vector<double> DLL_EXPORT getNonAugmentedOutputs();
protected:
    pugi::xml_parse_result DLL_EXPORT setDataFile(pugi::xml_document &doc, char* file_name);
    void DLL_EXPORT setDataFolder(char* folder_name);
    std::vector<char*> DLL_EXPORT findDataFiles();
    char* data_folder;
    std::vector<char*> file_names;
    std::vector<sample_type> input_data;
    /*
    sample_type m;
    m(0, 0) = 14.86;
    m(1, 0) = 0.24;
    */
    std::vector<double> augmented_outputs;
    std::vector<double> non_augmented_outputs;
    pugi::xml_parse_result result;

    void DLL_EXPORT setInputData();
    void DLL_EXPORT setAugmentedOutputs();
    void DLL_EXPORT setNonAugmentedOutputs();
    virtual int DLL_EXPORT trainAugmentedModel();
    virtual int DLL_EXPORT trainNonAugmentedModel();
};
}
#endif
\ifndef回归\u培训师\u H
#定义回归\u培训师\u H
#包括“MachineLearning.h”
#布拉格语一次
#ifndef DLL_导出
#定义DLL\u导出\u declspec(dllexport)
#恩迪夫
使用名称空间机器学习;
名称空间机器学习培训{
公营课程培训师{
公众:
DLL_导出回归训练器();
虚拟DLL_导出~RegressionTrainer();
std::vector DLL_EXPORT getInputData();
std::vector DLL_EXPORT getaugmentedoutput();
std::vector DLL_导出GetNoNugmentedOutput();
受保护的:
pugi::xml\u parse\u result DLL\u EXPORT setDataFile(pugi::xml\u document&doc,char*file\u name);
无效DLL_导出setDataFolder(字符*文件夹_名称);
std::vector DLL_导出findDataFiles();
char*数据_文件夹;
std::矢量文件名;
std::矢量输入_数据;
/*
m型样品;
m(0,0)=14.86;
m(1,0)=0.24;
*/
std::矢量增强_输出;
std::矢量非_增广_输出;
pugi::xml_parse_result;
void DLL_EXPORT setInputData();
void DLL_EXPORT setaugmentedoutput();
void DLL_EXPORT setNonaugmentedOutput();
虚拟int DLL_导出TraineAugmentedModel();
虚拟int DLL_导出培训非增强模型();
};
}
#恩迪夫
以下是MachineLearning.h的内容:

#include <vector>
#include <iostream>
#include <exception>
#include <fstream>
#include <string>
#include <dlib/svm.h>
#include "pugixml.hpp"

namespace MachineLearning{
// Here we declare that our samples will be 2 dimensional column vectors.  
    typedef dlib::matrix<double, 3, 1> sample_type;

// Now we are making a typedef for the kind of kernel we want to use.  I picked the
// radial basis kernel because it only has one parameter and generally gives good
// results without much fiddling.
    typedef dlib::radial_basis_kernel<sample_type> kernel_type;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括“pugixml.hpp”
名称空间机器学习{
//这里我们声明我们的样本将是二维列向量。
typedef dlib::矩阵样本类型;
//现在我们正在为我们想要使用的内核类型制作一个typedef
//径向基核,因为它只有一个参数,通常提供良好的性能
//结果没有太多麻烦。
typedef dlib::径向基核型;
}
这是我的RegressionTrainer.cpp文件:

#include "Stdafx.h"
#include "RegressionTrainer.h"
#include "dirent.h"

using namespace std;
using namespace dlib;
using namespace MachineLearning;

namespace MachineLearningTraining{

RegressionTrainer::RegressionTrainer(){
    file_names = findDataFiles();
}

RegressionTrainer::~RegressionTrainer(){

}

pugi::xml_parse_result RegressionTrainer::setDataFile(pugi::xml_document &doc, char *file_name){
    return doc.load_file(file_name);
}

void RegressionTrainer::setDataFolder(char *folder_name){
    data_folder = folder_name;
}

std::vector<char*> RegressionTrainer::findDataFiles(){
    DIR *dir;
    struct dirent *ent;
    std::vector<char*> file_names;
    if ((dir = opendir(data_folder)) != NULL) {
        /* print all the files and directories within directory */
        while ((ent = readdir(dir)) != NULL) {
            file_names.push_back(ent->d_name);
        }
        closedir(dir);
    }
    else {
        /* could not open directory */
        perror("Could not open directory");
    }
    return file_names;
}

std::vector<sample_type> RegressionTrainer::getInputData(){
    return input_data;
}

std::vector<double> RegressionTrainer::getAugmentedOutputs(){
    return augmented_outputs;
}

std::vector<double> RegressionTrainer::getNonAugmentedOutputs(){
    return non_augmented_outputs;
}

void RegressionTrainer::setInputData(){
    pugi::xml_document doc;

    for (unsigned i = 0; i < file_names.size(); i++){
        setDataFile(doc, file_names[i]);
        std::cout << "Load result: " << result.description() << endl;

        pugi::xml_node measures = doc.child("case").child("measures");

        sample_type m;
        int count = 0;

        for (pugi::xml_node measure = measures.first_child(); measure; measure = measure.next_sibling()){
            m(count, 0) = measure.text().as_double();
            count++;
        }
        input_data.push_back(m);
    }

}

void RegressionTrainer::setAugmentedOutputs(){
    pugi::xml_document doc;
    for (unsigned i = 0; i < file_names.size(); i++){
        setDataFile(doc, file_names[i]);
        std::cout << "Load result: " << result.description() << endl;

        pugi::xml_node output = doc.child("case").child("studyresults").child("averageangledeviation");
        augmented_outputs.push_back(output.text().as_double());
    }
}

void RegressionTrainer::setNonAugmentedOutputs(){
    pugi::xml_document doc;
    for (unsigned i = 0; i < file_names.size(); i++){
        setDataFile(doc, file_names[i]);
        std::cout << "Load result: " << result.description() << endl;

        pugi::xml_node output = doc.child("case").child("studyresults").child("averageangledeviationAR");
            augmented_outputs.push_back(output.text().as_double());
        }
    }

    int RegressionTrainer::trainAugmentedModel(){
        return 0;
    }

    int RegressionTrainer::trainNonAugmentedModel(){
        return 0;
    }
}
#包括“Stdafx.h”
#包括“RegressionTrainer.h”
#包括“dirent.h”
使用名称空间std;
使用名称空间dlib;
使用名称空间机器学习;
名称空间机器学习培训{
RegressionTrainer::RegressionTrainer(){
file_names=findDataFiles();
}
RegressionTrainer::~RegressionTrainer(){
}
pugi::xml_parse_result RegressionTrainer::setDataFile(pugi::xml_document&doc,char*文件名){
返回单据加载文件(文件名);
}
void RegressionTrainer::setDataFolder(char*文件夹名称){
数据\文件夹=文件夹\名称;
}
std::vector RegressionTrainer::findDataFiles(){
DIR*DIR;
结构导向;
std::矢量文件名;
如果((dir=opendir(数据文件夹))!=NULL){
/*打印目录中的所有文件和目录*/
while((ent=readdir(dir))!=NULL){
文件名。向后推(ent->d\U名);
}
closedir(dir);
}
否则{
/*无法打开目录*/
perror(“无法打开目录”);
}
返回文件名;
}
std::vector RegressionTrainer::getInputData(){
返回输入数据;
}
std::vector RegressionTrainer::GetAugmentedOutput(){
返回增加的输出;
}
标准::向量回归培训师::GetNoNugmentedOutput(){
返回非扩充的输出;
}
void RegressionTrainer::setInputData(){
pugi::xml_文档文档;
for(无符号i=0;istd::cout您的代码令人困惑:

public class RegressionTrainer

是C++还是C?你的代码的其他部分清楚地显示它是C++。因此,你必须总是放上精确的(或语法上相同的)代码。 回到您的问题,您不能导出类的成员。您必须从DLL导出整个类

然后问题就开始了。首先,您必须公开(导出或不导出,无所谓)类使用的所有类型(例如,
pugi::xml\u parse\u result
)。然后,您需要处理不同的编译器版本(甚至是VC2015、各种版本、调试/发布、编译器设置等)例如,VC2015调试版本上的
vector
将不同于发布版本。Service pack将使问题复杂化

简而言之:不要导出包含数据成员的整个类。即使整个数据是私有的,您也需要导出整个类,以便客户端(DLL的使用者)可以正确编译和链接(到代码)

那么,解决方案是什么

那么,只需导出一个帮助器类:

class DLL_EXPORT RegressionTrainerHelper
{
    RegressionTrainer* pCoreClass;
};
从此类中公开(导出)所有必需的方法(用于客户端)。只需将helper调用转发到real

现在,您可能想知道,您将需要导出基础的类型RegressionTrainer,然后又回到了相同的问题

好的,是和否。如果这个助手类是在DLL中编译的,
RegressionTrainer
将是真实的。如果不是,只需:

typedef int RegressionTrainer;
任何类型的指针大小相同(32位或64位)。因此,导出的整个类的大小始终与DLL和EXE中的大小匹配

编辑 例如,有一个XML解析器类ParseXML,但它使用comlpex数据成员,您有一个方法
Parse

class ParseXML
{
// complex data members
// some private OR public datamembers and functions, you dont want/need to export
public:
void Parse(const char*); // or something different
};
您可能只希望通过helper类导出
解析

class DLL_EXPORT Exported_ParseXML
{
private:
ParseXML* pCoreXMLInstance;
public:
Exported_ParseXML()
{
  // implementation in CPP
  pCoreXMLInstance = new ParseXML();
}
// The function!
void Parse(const char* pData)
{
  // FORWARD
  pCoreXMLInstance->Parse(pData);
}
客户端将只使用导出的类:

Exported_ParseXML parser;
parser.Parse("XML-data");

服务器编译器(DLL)会将
ParseXML
视为真实的类类型。但客户端(EXE或其他DLL)会将
ParseXML
视为
int
。您必须弄清楚这一点!

您的代码令人困惑:

public class RegressionTrainer

是C++还是C?你的代码的其他部分清楚地显示它是C++。因此你必须总是P