C++ DLL 不导出函数
C++ DLL not exporting functions
我正在开发一个C++库,用于在Visual Studio 2013(C++ 11)中导出为DLL,我遇到了一个挑战,即库一旦被另一个程序作为外部依赖项导入,就包含我想要的类,但不包含类的任何功能。
外部依赖项中的类视图
我包含一个特定的类,它应该是此DLL导出的一部分。
这是我的回归训练器类头文件:
#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
以下是 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;
}
这是我的回归训练器.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;
}
}
欢迎任何想法!
你的代码令人困惑:
public class RegressionTrainer
这是C++还是 C#?代码的其他部分清楚地表明它是C++的。因此,您必须始终放置精确(或语法相同)的代码。
回到您的问题,您无法导出类的成员。必须从 DLL 导出整个类。
然后问题开始开始。首先,您必须公开(导出与否,无关紧要)类使用的所有类型(例如pugi::xml_parse_result
)。然后,您需要处理不同的编译器版本(甚至是VC2015,各种版本,调试/发布,编译器设置等)。例如,VC2015 调试版本上的vector
将与发布版本不同。服务包会使问题复杂化。
简而言之:不要导出具有数据成员的整个类。即使整个数据都是私有的,您也需要导出整个类,以便客户端(DLL 的使用者)可以正确编译和链接(到代码)。
那么,解决方案是什么?
好吧,只需导出一个帮助程序类:
class DLL_EXPORT RegressionTrainerHelper
{
RegressionTrainer* pCoreClass;
};
从此类公开(导出)所有必需的方法(对于客户端)。您只需要将呼叫从助手转发到真实类。
现在,您可能想知道,您将需要导出基础类型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
};
您可能只想通过帮助程序类导出Parse
。
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
。你必须弄清楚这一点!
- 使用c#访问c++dll中带有char*参数的函数时发生AccessViolationException
- Visual c ++,使用字符串引用/指针调用 dll 函数
- 来自 DLL 的函数调用 [表观调用的括号前面的表达式必须具有(指向-)函数类型]
- C++ DLL 引用C++.exe中的函数和类
- 如何使用导出的函数交叉编译 DLL
- 如何在窗口中使用注入的 dll 中的参数调用函数
- 在 Microsoft Access SQL 中调用自定义 DLL 函数时传递的内存地址无效
- 加载由 MATLAB Coder 生成的带有函数的 DLL,该函数调用外部函数
- PowerShell 使用结构类型参数调用 C++ DLL 的导出函数
- 从DLL导出函数,LoadLibrary()需要用TEXT转换的字符串才能编译而不会出错
- 从 C#-DLL 调用函数的 C++ 失败
- 如何在 DLL 内的成员函数中使用互斥/关键节
- 调用 "project" 函数和调用 DLL 函数之间的区别
- 函数指针分配在创建 DLL 后导致错误
- 从动态加载的 dll 内部调用C++函数
- 函数声明中的 WINAPI 标识符C++ DLL 入口点函数中的标识符
- LNK2019某些类函数,但不在其他类函数(DLL 中的模板类)上
- 从库导入函数./ DLL 文件
- 从 ntdll 调用 Nt 函数.dll在 Win32 环境中,C++
- 如何使用ctypes将python列表传递给C函数(dll)