我有一个C++项目,由于其目录结构被设置为静态库A,它链接到共享库B,它链接到可执行文件C.(这是使用CMake的一个跨平台的项目,所以在Windows上我们得到的A.lib,B.dll和C.exe,和在Linux上我们得到的libA.a,libB.so和C).图书馆A有一个初始化函数(A_init在定义A/initA.cpp),即从库调用B的初始化函数(B_init,定义于B/initB.cpp),从C主要调用.因此,当链接时B,A_init(和所有符号中定义的initA.cpp)被链接到B(这是我们期望的行为).
问题在于,A库还定义了一个动态加载的函数(Af,在A/Afort.f其中定义)(即LoadLibrary/ GetProcAddress在Windows上和dlopen/ dlsym在Linux上).由于没有Af来自库的引用B,A/Afort.o因此不包括符号B.在Windows上,我们可以通过使用pragma人工创建引用:
#pragma comment (linker, "/export:_Af")
Run Code Online (Sandbox Code Playgroud)
由于这是一个pragma,它只适用于Windows(使用Visual Studio 2008).为了让它在Linux上运行,我们尝试将以下内容添加到A/initA.cpp:
extern void Af(void);
static void (*Af_fp)(void) = …Run Code Online (Sandbox Code Playgroud) 我正在使用Boost.Test进行单元测试.
由于几个原因,我想在不同的静态库上编写单元测试用例.
问题是,当我这样做时,自动注册器不起作用.
例如,如果我有类似的东西:
// foo_tests.cpp
#define BOOST_TEST_MODULE "Foo"
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_CASE( Bar )
{
BOOST_CHECK( false );
}
// used to generate libFooTests.a
// main.cpp
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MAIN
#include <boost/test/unit_test.hpp>
// used to generate main.o
Run Code Online (Sandbox Code Playgroud)
然后,如果我将main.o与libFooTests.a链接并执行最终的二进制文件,它会说:
Test setup error: test tree is empty
如果我直接从源代码创建二进制文件,一切正常,但我不能使用自动注册在静态库中编写单元测试.
我能做到吗?
我需要定义一些宏吗?我需要从libFooTests.a导出一些符号?
谢谢!
假设我有一些每类数据:(AandB.h)
class A
{
public:
static Persister* getPersister();
}
class B
{
public:
static Persister* getPersister();
}
Run Code Online (Sandbox Code Playgroud)
......还有很多课程.我想做的事情如下:
persistenceSystem::registerPersistableType( A::getPersister() );
persistenceSystem::registerPersistableType( B::getPersister() );
...
persistenceSystem::registerPersistableType( Z::getPersister() );
Run Code Online (Sandbox Code Playgroud)
......为每个班级.
我的问题是:有没有办法自动构建每类数据列表,这样我就不必枚举大块中的每个类型(如上例所示)?
例如,您可以这样做的一种方法是:(AutoRegister.h)
struct AutoRegisterBase
{
virtual ~AutoRegisterBase() {}
virtual void registerPersist() = 0;
static AutoRegisterBase*& getHead()
{
static AutoRegisterBase* head= NULL;
return head;
}
AutoRegisterBase* next;
};
template <typename T>
struct AutoRegister : public AutoRegisterBase
{
AutoRegister() { next = getHead(); getHead() = this; }
virtual void registerPersist()
{
persistenceSystem::registerPersistableType( T::getPersister() …Run Code Online (Sandbox Code Playgroud) 我有以下情况:假设我有一堆类型(仿函数),我想在编译期间注册/编译,最好是像boost :: mpl :: vector.你知道这么做的诀窍吗?
我的愿望是拥有实现仿函数类型和注册文件的hpp文件,其中宏将类型引入编译.
例如
// registered.hpp
REGISTER("functor1.hpp") // implementation
REGISTER("functor2.hpp")
...
boost::mpl::vector<...> types; // full registration vector
Run Code Online (Sandbox Code Playgroud)
希望这是有道理的.谢谢
我有一个应用程序和DLL文件中的几个插件.插件通过导出库使用应用程序中的符号.应用程序链接在几个静态库中,这是大多数符号的来源.只要应用程序使用符号,这就可以正常工作.如果那里没有使用符号,我在编译DLL时会遇到链接器错误.
如何强制导出仅在插件中使用的符号?
为了触发导出,我尝试过这样的事情:
class MyClassExporter
{
MyClass mInstance;
public:
MyClassExporter() {}
};
static MyClassExporter TheMyClassExporter;
Run Code Online (Sandbox Code Playgroud)
在其中一个静态库中,应用程序由强制导出组成,这不起作用.
回应Greg(感谢答案)并澄清:我要强制导出的类是MyClass(已定义__declspec(...),具体取决于我想要导出或导入).MyClassExport是我试图强制将未使用的(就应用程序而言)符号包含在应用程序中.我想"触摸"符号,以便链接器将它们识别为已使用并将它们包含在应用程序中,以便它可以将这些符号导出到我的插件中.将静态库链接到插件不是一种选择,因为它们包含可复制的单例(app和DLL各自都有自己的静态变量副本).
我目前正面临着一个令人讨厌的C++问题.
实际上,我甚至不明白为什么在过去的20年里我没有面对它:(
在我目前的上下文中,我们大量使用与我们专有的静态库静态链接的c ++可执行文件(主要是在Linux嵌入式系统中).出于技术和优化原因,我们确实使用静态库.
事实上,在过去的几年里,我曾经创建了共享库...
所以我开始用静态类成员编写一些类.如下:
class Inner
{
public:
Inner()
{
std::cout << "CTOR Inner" << std::endl;
}
};
class A
{
static Inner _inner;
...
};
// in the .cpp
Inner A::_inner;
///////////////////////
Run Code Online (Sandbox Code Playgroud)
非常基本的用例,不是吗?
但在我的单元测试中,与lib链接,我无法std::cout在控制台中看到该语句.然而,如果我将我的类Inner和A移动到可执行源代码中......它可以正常工作.
我确信这是一个非常基本的问题,我意识到过去几年我从未面对过这个问题.这是与编译器有关的问题吗?请注意,我在Windows和Linux上测试了这两种情况(Debian,Gcc 4.9).
欢迎任何想法.
Z.
我想在共享库中初始化一些查找表,我想看看这是否是一种有效的方式,如果它继续在更多的库中使用它我将要编写.
typedef std::map<std::string, int> NAME_LUT;
NAME_LUT g_mLUT;
namespace
{
bool OneTimeInit()
{
::g_mLUT.insert(NAME_LUT::value_type("open", 1));
::g_mLUT.insert(NAME_LUT::value_type("close", 2));
return true;
}
bool bInit = OneTimeInit(); // Just to make initialization happen
}
Run Code Online (Sandbox Code Playgroud)
它似乎在Visual Studio和gcc(Linux)上都能正常工作.只有gcc抱怨bInit没有在任何地方使用.
bInit未使用),或语言不允许(由于副作用).OneTimeInit声明静态是否有意义?(即使用static bool OneTimeInit() {...}),或单独使用命名空间是使其成为此编译单元唯一的更好方法我有一个带有我的main()函数的翻译单元和另一个没有 main 的翻译单元。假设即使我只控制第二个而无法触摸第一个。
现在,由于我不会讨论的原因,我希望能够在运行之前运行一些代码main()。我知道这可以通过使用函数调用初始化全局变量来完成,但我想隐藏这一点 - 尽可能少地使用宏(我敢说不使用宏吗?可能不可能,C++ 中没有适当的静态块)
什么是优雅的,或者我们可以说,不是很丑的做这件事的方式?更清楚地说,我正在寻找可以多次使用此功能的东西,而不仅仅是让它工作一次的东西。我希望它尽可能接近:
// ... at global scope ...
static {
// my code here
}
Run Code Online (Sandbox Code Playgroud)
PS:这个问题与这个关于初始化静态类成员的问题有关,但不一样。它还希望清楚地反驳这个声明,它不能在 C++ 中完成。
注意:是的,我知道静态初始化顺序失败,不需要提醒我……而且我不是要求绕过它的东西。显然,静态运行代码需要一些谨慎。
我正在学习staticC中的变量,并且知道static变量的内存是在编译时分配的(在编译期间需要分配多少内存并且在编译时计算其虚拟地址,在程序加载时分配实际内存)在任一数据中segment/.bss取决于是否已初始化
我在一些网站帖子中看到,由于对象/变量将采用的大小是基于变量类型预定义的,因此内存在编译时分配.但是,如果局部static变量在函数中定义且其范围仅在函数内,我不理解这种情况的必要性.
请考虑以下代码段:
void func()
{
static int i;
/*some logic*/
}
void func1()
{
static int data[10] = {1,2,3,4,5,6,7,8,9,10};
/*some logic*/
}
int main()
{
/*logic not involving func() and func1()*/
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,函数func并func1没有在程序中调用,但是static一旦程序加载(从我学到的)实际上没有使用,就会分配这些函数中的变量的内存.因此,有了这个缺点,为局部static变量分配内存的用途是什么.为什么编译器在通过函数时不能在数据段中为它们分配内存.
我已经经历了关于此的堆栈溢出问题,无法得到确切的答案 请帮助!
c++ ×9
boost-test ×1
c ×1
dll ×1
idioms ×1
linker ×1
linux ×1
macros ×1
namespaces ×1
plugins ×1
static ×1
static-block ×1
templates ×1
unit-testing ×1
visual-c++ ×1