我正在开发一个具有多个类似代码路径的项目,我想将它从主项目分离到插件中.该项目必须保持跨平台兼容,我所研究的所有动态库加载API都是特定于平台的.
创建动态库加载系统的最简单方法是什么,可以在多个操作系统上编译和运行而无需额外修改代码?理想情况下,我想编写一个插件,并使其适用于项目支持的所有操作系统.
谢谢.
在此示例中,函数被传递给隐式实例化的函数模板.
// Function that will be passed as argument
int foo() { return 0; }
// Function template to call passed function
template<typename F>
int call(F f) {
return f();
}
template<typename F, typename A>
int call(F f, A a) {
return f(a);
}
int a = call(foo);
Run Code Online (Sandbox Code Playgroud)
我们可以通过添加重载来破坏此代码foo().
int foo(int i) { return 0; }
Run Code Online (Sandbox Code Playgroud)
名称" foo"现在不明确,示例将不再编译.这可以通过显式提供函数指针类型信息来进行编译.
int (*func_takes_void)() = foo;
int a = call(func_takes_void);
int (*func_takes_int)(int) = foo;
int b = call(func_takes_int, 0);
Run Code Online (Sandbox Code Playgroud)
http://coliru.stacked-crooked.com/a/e08caf6a0ac1e6b9
是否可以推断出函数指针类型?如果是这样,为什么我的尝试下面不起作用,这是正确的方法? …
如果有以下程序的定义行为是什么?
#include <iostream>
#include <exception>
#include <cstdlib>
void i_throw()
{
std::cout << "i_throw()" << std::endl;
// std::terminate() is noexcept so if the terminate handler throws...
// then the terminate handler is called...
// std::terminate is [[noreturn]] so don't return
try
{
throw 7;
}
catch(...)
{
std::cout << "caught exception, re-throw()-ing" << std::endl;
throw;
}
std::cout << "got here!" << std::endl;
std::abort();
}
int main()
{
std::set_terminate(i_throw);
throw;
std::terminate();
}
Run Code Online (Sandbox Code Playgroud)
使用gcc和clang我得到以下输出:
i_throw()
caught exception, re-throw()-ing
Aborted (core dumped)
Run Code Online (Sandbox Code Playgroud)
在前几条评论后编辑的示例.
(我不知道为什么我有两个 …
数学库经常基于FLOPS进行比较.当我向几个不同的数学库展示FLOPS与大小的点集时,向我传达了什么信息?
如果比较是在同一算法的两个实现之间或两个不同硬件上的相同软件之间进行比较,那么作为性能度量的FLOPS会更有意义.我不明白为什么它是比较像矩阵矩阵乘法这样的东西的合适或流行的方法.
暗示只是底层算法几乎相同,并且通过最小化开销获胜来最快地为浮点单元提供信息的代码?
例子比比皆是.
http://eigen.tuxfamily.org/index.php?title=Benchmark
https://code.google.com/p/blaze-lib/wiki/Benchmarks
另一方面,这些LAPACK和Armadillo基准测试使用绝对时间进行给定操作,这对我来说更有意义.
http://www.netlib.org/lapack/lug/node71.html
http://arma.sourceforge.net/speed.html
相关:
为什么std :: stof,std :: stod,std :: stold抛出异常的原因是什么?
http://en.cppreference.com/w/cpp/string/basic_string/stof
输入错误是一个常用的例子,当通过异常进行错误处理不合适时(通常用"异常情况"的古怪循环推理表达,但仍然是一个很好的例子).并不是说其他错误处理机制在C++标准库中以某种方式被禁止.例如,另一个C++ 11新手,该std::unordered_map::insert系列,表示在std::pair<iterator,bool>返回类型中使用第二个元素失败.std::unordered_map::insert函数内部的失败似乎比输入错误更"特殊".在不尝试插入的情况下,可以保证插入成功但不解析它就不可能保证解析成功.
我只是想知道当这些功能被接纳到标准中时的基本原理.希望它可以在某个地方发布,或者委员会成员可以匆匆而过,并对此有所了解.我不是要求就异常与其他机制的优缺点进行全面论述.
在Python标准库文档中,示例实现__subclasshook__是:
class MyIterable(metaclass=ABCMeta):
[...]
@classmethod
def __subclasshook__(cls, C):
if cls is MyIterable:
if any("__iter__" in B.__dict__ for B in C.__mro__):
return True
return NotImplemented
Run Code Online (Sandbox Code Playgroud)
CPython的实现collections.abc确实遵循__subclasshook__它定义的大多数成员函数的这种格式.明确检查cls参数的目的是什么?
C++ 11标准要求在内存中为类的非静态数据成员排序,但是然后专门为具有不同访问说明符的成员划分豁免.
为什么呢?
§9.2.13
分配具有相同访问控制(第11条)的(非联合)类的非静态数据成员,以便后面的成员在类对象中具有更高的地址.具有不同访问控制的非静态数据成员的分配顺序未指定(第11条).实施对齐要求可能导致两个相邻成员不能立即分配; 因此,可能需要空间来管理虚拟功能(10.3)和虚拟基类(10.1).
标准的这一部分已经出现在stackoverflow之前,但我认为它从未被解释过.
我想通常使用libdl动态加载C ++。问题是在运行时识别已被名称篡改的符号。
如此处所述,一种解决方案是通过使用extern“ C”删除名称修饰。
http://www.tldp.org/HOWTO/C++-dlopen/theproblem.html
该解决方案具有将动态加载的资源限制为C样式接口的缺点。例如,动态加载的函数不能是重载函数。
什么是克服此限制的好方法?
一种可能的解决方案是使用链接函数命名库源代码的工具,以在需要链接库时获取修改后的名称。llvm是否为此提供工具?
可能一个笨拙的解决方案是使用函数签名的函数,使用具有签名的函数创建伪代码,将其与用于生成程序集的标志一起使用的编译器传递到编译器,解析输出以获取错误的名称并返回整齐的名称作为字符串。然后可以将字符串传递给dlsym()。
为了使问题更具体,这里有两个示例程序,它们说明了外部“ C”解决方案在不修改库代码的情况下无法动态加载的内容。第一个以传统的C ++方式动态链接库。第二个使用dlopen。在第一个程序中链接重载函数很简单。在第二个程序中没有简单的方法链接重载函数。
程序1:加载时动态链接
main.cpp
// forward declarations of functions that will be linked
void say(int);
void say(float);
int main() {
int myint = 3;
say(myint);
float myfloat = 5.0f;
say(myfloat);
}
Run Code Online (Sandbox Code Playgroud)
说
#include <iostream>
//extern "C" function signatures would collide
//extern "C" void say(int a) {
void say(int a) {
std::cout << "The int value is " << a << ".\n";
}
//extern "C" void say(float a) {
void say(float …Run Code Online (Sandbox Code Playgroud) 我的理解是gdb可以监视正在运行的程序的完整状态。我可以保存在断点处暂停的gdb会话并在以后恢复该会话吗?
我的第一次尝试只是在第一个gdb会话中生成了一个核心转储,该会话在断点处暂停,然后使用该核心转储来启动第二个gdb会话。
这导致以下错误。
Program terminated with signal SIGTRAP, Trace/breakpoint trap.
Run Code Online (Sandbox Code Playgroud)
因此,将断点信息插入程序状态,很有趣。在第二次尝试中,我执行了相同的操作,但是这次我在第二次会话中添加了与第一次会话相同的断点。
仍然,我得到同样的错误。
我可以保存并重新启动gdb会话吗?如果是这样,怎么办?
我认为这并不直接相关,但我也收到了此警告。
warning: core file may not match specified executable file.
Run Code Online (Sandbox Code Playgroud)
是gdb只是简单地声明这种事情通常是可能的,还是gdb认为这可能是在运行的会话中发生的?我相信,生成核心转储的同一可执行文件正在gdb下运行。
编辑:对于其他人,这个问题:保存进程的内存以供以后使用?添加到Mats Petersson的答案和指向本文的链接:http : //blogs.msdn.com/b/oldnewthing/archive/2004/04/20/116749.aspx,这是一本有趣的文章。链接的问题还建议将进程包装在VM中。
使用 CMake,是否有一种方法可以生成构建系统,如果共享库的源代码更改而不更改其标头,则不会重新链接下游的所有内容?
在 Makefiles 中,我在共享库本身上使用了一个只有订单先决条件的规则,并在库头上使用了常规先决条件来获得这种效果。
我知道这并不能严格保证生成正确的构建,例如您可以从共享库中删除函数定义,但这是为了快速重建调试构建,根据我的经验,它几乎总是产生正确的构建。我想有一两次我遇到了运行时链接器错误,但在那种奇怪的情况下,像往常一样运行构建并没有太大的麻烦。
尽管如此,如果有充分的理由表明这实际上是一个糟糕的想法并且不应该这样做,那也可能是一个答案。