在使用Haskell FFI到C/C++时,我最近遇到了C++内联函数的问题.也就是说,g ++并不真正内联声明的函数inline,并为它们生成符号.最终,当ghci尝试加载调用内联函数的目标文件时,这会生成链接器错误:
Loading object (static) solveeq.o ... done
Loading object (dynamic) /usr/lib/gcc/x86_64-linux-gnu/4.6/libstdc++.so ... done
final link ... ghc: solveeq.o: unknown symbol `_ZN5Eigen8internal19throw_std_bad_allocEv'
Run Code Online (Sandbox Code Playgroud)
这里,_ZN5Eigen8internal19throw_std_bad_allocEv是inline仅在标题的Eigen C++库中的函数,以某种方式被视为实函数并给出了链接器符号.solveeq.o是我的目标文件,它对该函数进行(间接)调用.环境是Ubuntu 12.04 64bit,ghc 7.4.1.
问题是这样的:我可以extern "C" 用来阻止C++为我自己的函数装饰函数名.但我不能/不应该更改其他人定义的C++标头(原因很明显).在我看来,编译器不应该首先为此内联定义创建一个函数来导致此错误.原因很简单.如果有问题的函数是真正内联的,我不会得到链接器错误.如果编译器变得聪明并决定为它创建一个真正的函数,我会得到这样的错误(或者我在其他地方读到的同一函数的多个定义).所以现在,编译/链接的正确性取决于编译器的情绪.
此外,我认为像这样的链接器问题实际上会破坏仅限标头的C++库(它们具有吸引力),因为现在无法使用它们进行导出extern "C".
这是c ++的设计问题还是仅仅是一个g ++问题?我的问题是,有没有办法阻止c ++编译器或g ++不内联内联函数?例如,是否有一个命令行选项?(修改源代码是不可能的,因为它们是库代码.)
另外,我很好奇C++ STL是如何处理这个问题的.它们也只是标题吗?
我有一些琐碎的日志记录:
BOOST_LOG_TRIVIAL(trace) << make_trace_record();
Run Code Online (Sandbox Code Playgroud)
现在make_trace_record是一个有点贵的功能(不要问为什么,这很复杂).我只想在日志当前通过过滤时调用它.我怎样才能做到这一点?我没有看到明确调用严重性过滤器的方法.
谁能告诉我什么时候在C中使用typedef?在以下代码中,我收到警告gcc:
warning: useless storage class specifier in empty declaration
typedef struct node
{
int data;
struct node* forwardLink;
} ;
Run Code Online (Sandbox Code Playgroud) DynamicException和throwDyn和throwDynTo曾经是在Control.OldException模块.现在这种OldException情况一去不复返了,依赖它的软件包就破了.
是否有相应DynamicException的ExtensibleException包装或其他地方?我想以最小的改变逃脱.
上下文:我正在尝试使用GHC 7.6.1构建lambdabot.损坏的文件Signal.hs在lambdabot-utils.
更新是否有某种指南将旧的异常代码移植到新的可扩展异常中?在几个地方lambdabot使用OldException,似乎不可能快速修复.
#include <locale>
#include <iostream>
int main()
{
std::locale::global(std::locale("en_US.utf8"));
std::wcout << L"H??£? ?ø???\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这与libstdc ++(gcc和clang)一样正常工作,但只用libc ++打印第一个字符(恰好是ASCII).我在Gentoo Linux上使用libcxx-0.0_p20140322.
这是libc ++中的已知错误,还是我不知道如何烹饪?
更新1.我试过了
std::locale::global(std::locale("en_US.utf8"));
std::locale::global(std::locale(""));
std::setlocale(LC_ALL, "en_US.utf8");
std::setlocale(LC_ALL, "");
Run Code Online (Sandbox Code Playgroud)
这一切都做同样的事情.
更新2.为简单起见,宽字符串文字在这里.当以任何其他方式获得字符串时发生同样的事情(从UTF-8转换,从二进制文件读取,......)
在无符号整数中交换第一个(最低有效)2个不同连续位的快速而优雅的方法是什么?
例如
100100 -> 100010
110011 -> 110101
Run Code Online (Sandbox Code Playgroud)
到目前为止,我想出了这个:
unsigned long long special_swap(unsigned long long number)
{
if (number & 1)
return (number + 1) ^ ((number ^ (number + 1)) >> 2);
number = ~number;
return ~((number + 1) ^ ((number ^ (number + 1)) >> 2));
}
Run Code Online (Sandbox Code Playgroud)
我对上述解决方案的最大不满是它使用了该if指令.
在C++中引入新的中缀运算符很容易
// User-defined infix operator framework
template <typename LeftOperand, typename Operation>
struct LeftHelper
{
const LeftOperand& leftOperand;
const Operation& operation;
LeftHelper(const LeftOperand& leftOperand,
const Operation& operation)
: leftOperand(leftOperand), operation(operation) {}
};
template <typename LeftOperand, typename Operation >
auto operator < (const LeftOperand& leftOperand,
Operation& operation)
{
return LeftHelper<LeftOperand, Operation>(leftOperand, operation);
}
template <typename LeftOperand, typename Operation, typename RightOperand>
auto operator > (LeftHelper<LeftOperand, Operation> leftHelper,
const RightOperand& rightOperand)
{
return leftHelper.operation(leftHelper.leftOperand, rightOperand);
}
// Defining a new operator
#include <cmath>
static …Run Code Online (Sandbox Code Playgroud) 我想写一些C代码(好吧,如果它只适用于Linux)来动态加载一个新的共享库,然后从中调用一个方法(在运行时确定).这似乎已经成为可能,因为java可以动态加载本机库,然后从它们调用方法.
例如,我想做类似的事情:
int main() {
libinfo_t * lib_details = load_shared_library("libfoo.so");
run_method(lib_details, "bar", 7);
}
Run Code Online (Sandbox Code Playgroud)
这将使用参数7调用方法'bar'(bar是编译为libfoo.so的方法).
用例详细信息:
我想编译一个二进制文件,它加载目录中的所有共享库,并在原始程序的内存上下文中运行每个共享库的一些方法.我希望能够通过在目录中添加/删除共享库来快速启用或禁用它.
概念证明:
看来这应该是可能的,基于java设法动态链接jni代码的方式.您可以使用System.load(),并加载您选择的库.再加上内存编译,似乎它允许你从任意库运行任意函数.http://www.java2s.com/Code/Java/JDK-6/CompilingfromMemory.htm
我试过的事情:
我已经查看了'uselib'的联机帮助页面,这看起来很有用,但是一旦我加载它,我不确定该如何处理它.
一些谷歌搜索返回http://dyncall.org/,但这不是我需要的 - 这个项目仍然需要一个函数指针来进行函数调用.
即使没有具体的答案,我也会感激任何指向下一步的指针.谢谢!
我有一个C++ Windows程序无法设置退出代码.该程序非常复杂,我目前无法通过简单的测试用例重现这一点.我知道程序调用exit(1)因为我在该行上有一个断点.在我跳过它之后,调试器(VS2010)立即打印The program program.exe has exited with code 0 (0x0).当我从shell运行它时,%ERRORLEVEL%也设置为0.
我使用subsystem:console和普通main(没有WinMain).
这仅发生在Windows Server 2008 R2上,而不是在我的Windows 8.1笔记本电脑上.我在两者上运行相同的可执行文件.
我曾尝试使用exit,_exit,ExitProcess,和return(违规通话中main),但这些都不似乎有什么影响.我也试图返回其他代码,也没有结果.
有一个类似的问题,但我无法重现其中描述的结果.我的程序确实使用线程.
我该如何处理调试此问题?我很困惑.
在使用g ++的linux上,如果我设置了utf8全局语言环境,那么wcin正确地将UTF-8转码为内部wchar_t编码.
但是,如果我使用经典语言环境并将UTF8语言环境灌输到wcin中,则不会发生这种情况.输入完全失败,或者每个字节独立转换为wchar_t.
使用clang ++和libc ++,既不设置全局语言环境也不设置语言环境wcin.
#include <iostream>
#include <locale>
#include <string>
using namespace std;
int main() {
if(true)
// this works with g++, but not with clang++/libc++
locale::global(locale("C.UTF-8"));
else
// this doesn't work with either implementation
wcin.imbue(locale("C.UTF-8"));
wstring s;
wcin >> s;
cout << s.length() << " " << (s == L"áéú");
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输入流仅包含áéú字符.(它们是UTF-8,而不是任何单字节编码).
这是符合标准的吗?我不应该单独留下全局区域设置imbue而是使用吗?
是否应将任何描述的行为归类为实施错误?