DLL – 在 DLL 初始化时填充的静态向量,向客户端程序返回零大小
DLL – static vector which is filled up at DLL’s initialization time, returns zero size to the client program
我在 DLL 项目中遇到以下问题:
在 DLL 端:
-
在 DLL 中,我声明了一个静态向量,如下所示:
static std::vector<FilterProcessor::FilterInfo*> TableOfContents;
- 在静态成员的 DLL 初始化时,我正在向上述向量添加一些条目。
-
我已经定义了一个 extern "C" 全局函数 (getTocPointer()),当它从客户端程序调用时,它会返回一个指向向量的指针。
extern "C" __declspec(dllexport) std::vector<FilterProcessor::FilterInfo*>* __cdecl getLibraryTOC();
在客户端的程序端:
- DLL 库加载没有任何问题
- 调用
getProcAddress()
函数时,getTocPointer()
函数的地址将正确返回给客户端程序。 - 实际上,当我在DLL端执行调试过程时,客户端程序调用上述函数,执行过程进入其中。
- 但是,向量的大小为零,并且没有任何在初始化时添加到其中的内容。它似乎指向另一个矢量对象。
我真的不明白这里到底出了什么问题。
在初始化时向此向量添加条目的方式是正确的方法吗?
如果是,当客户端程序调用 getLibraryTOC() 函数时可能出现什么问题?
提前致谢
乔治
如果向量的静态全局定义出现在头文件中,那么是的,您确实有多个不同的向量。 将关键字static
更改为extern
,以使头文件声明向量而不是定义它,然后在实现文件中只添加一个定义。
然后,您可能会遇到静态初始化顺序惨败。 如果vector
是在与尝试向其添加条目的代码不同的编译单元中定义的,则无法保证vector
对象处于活动状态。 尝试使用构造函数尚未运行的vector
是未定义的行为 - 它可能很容易表现为构造函数在之后运行并将内容设置为零长度(默认构造函数应该如此),但可能会出现许多其他问题。
您可以使用本地静态来避免 SIOF。
std::vector<FilterProcessor::FilterInfo*>& table_of_contents()
{
static std::vector<FilterProcessor::FilterInfo*> singleton;
return singleton;
}
在将访问全局的每个位置(包括填充向量的初始化逻辑)以及getLibraryTOC()
导出的函数中,请改为调用访问器函数。
这一切都适用于具有多个编译单元的任何C++软件。 当你有一个DLL时,事情变得更加复杂,因为DLL和EXE是分开编译和链接的,可能具有不同的设置,不同的编译器,甚至完全不同的语言。 跨 DLL 边界共享复杂对象确实很麻烦。 如果 DLL 和 EXE 始终同时重新编译,则可以工作。 但是,如果您尝试分发 DLL 以供编写 EXE 代码的另一方使用,则强耦合将很快变得无法忍受。
更好的方法是从 DLL 边界中隐藏库对象,并仅传递基元或 OS 托管的类型。 例如:
#define DLLAPI __declspec(dllexport) __cdecl
extern "C" DLLAPI int32_t getLibraryTocCount()
{ return table_of_contents.size(); }
extern "C" DLLAPI BSTR getLibraryTocName(int index)
{ return ::SysAllocString(table_of_contents[index].name.c_str(); } // assumes std::wstring
// etc
我实现的库包含以下代码(在简要说明中):
- 实现库目录的索引类
- 名为 Filter01、Filter02 等的音频筛选器的集合。
索引.h
struct LIB_SPECS Library_TableOfContents
{
static bool addTOCEntry(FilterInfo* Filter_Info); // add an entry to the TOC
static std::vector<FilterInfo*> TableOfContents; // TOC
};
/*-------------------------------------------------------------------
Called from the client program to return the pointer to TOC */
extern "C" LIB_SPECS std::vector<FlterInfo*>* __cdecl getLibraryTOC();
索引.cpp
/* Define / Initialize static variables */
std::vector<FilterInfo*> Library_TableOfContents::TableOfContents = {};
//=====================================================================
bool Library_TableOfContents::addTOCEntry(FilterInfo* Filter_Info)
{
Library_TableOfContents::TableOfContents.push_back(Filter_Info);
return false;
}
//======================================================================
std::vector<FilterInfo*>* getLibraryTOC()
{
return &Library_TableOfContents::TableOfContents;
}
对于库中的每个音频过滤器:
过滤器xx.h
class LIB_SPECS Filterxx
{
public:
static struct FilterInfo
{
public:
std::string filterName;
std::string filterDescription;
// other filter info
FilterInfo(); // FilterInfo constructor
} Filter_Info;
virtual String doSomeWork(int AvatarId);
virtual void deleteFilter() = 0;
};
过滤器xx.cpp
Filterxx::FilterInfo Filterxx::Filter_Info("Filterxx", “A filter description e.g. Low pass Filter ” ); //
FilterInfo::FilterInfo(std::string name, std::string description)
{
Filter_Info.filterName = name;
Filter_Info.filterDescription = description;
Library_TableOfContents::addTOCEntry(&Filter_Info);
}
// other filter functions
getLibraryTOC() 函数从客户端程序调用以获取目录,以便向用户显示。 正如我所说,它确实是由客户调用的,但在调用时,目录的大小似乎为零。
- "unknown ca"自生成的 CA、证书和客户端/服务器
- 如何将函数集合传递给客户端类,以便将它们当作客户端类本身的成员使用
- 如何从客户端为COM服务器设置dll搜索路径?
- 具体的模板正文,它在 dll 中并在客户端中调用
- DLL – 在 DLL 初始化时填充的静态向量,向客户端程序返回零大小
- 使用ACE_dll动态加载客户端C++dll,错误为未处理的异常
- 在DLL中分配内存并将其指针提供给客户端应用程序,这是不是一种糟糕的做法
- 在 DLL 中完成分配时释放客户端中的内存
- 在DLL客户端中使用dllimport时出错
- 在构建dll时,我需要在客户端的标头中提供多少个父级作为__declspec(导出)
- 如果在 DLL/Lib 中定义了对象,是否可以在客户端中实例化对象?
- 将 c# asp.net Web 应用程序与C++ dll 链接时,是在服务器或客户端上运行的 dll 代码
- 一个C++客户端无法使用我们新的 COM 注册的 .NET .dll加载,另一个客户端可以正常工作
- 是否可以为同时使用Windows和Linux的客户端使用相同的DLL
- 如何在客户端实现在DLL中声明的方法
- 在Microsoft Visual c++ 2015中编译DLL -警告C4251需要有DLL接口供类的客户端使用-当使
- 命名管道c#服务器c++ .dll客户端不工作
- 客户端需要在他们的机器上安装OpenCv来运行c++ DLL(使用OpenCv库)吗?
- 如何在客户端PC中使用编译后的DLL而不安装Windows SDK ?
- 您是否可以拥有一个具有管理员权限的DLL,该DLL从仅具有用户级权限的客户端应用程序链接