热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

解决C++代码在R中加载时出现的‘符号未找到’错误

本文探讨了一个在MacMavericks系统上使用Clang++成功编译但通过RCMDSHLIB构建并在R中加载时遇到‘符号未找到’错误的C++程序问题。文章详细分析了错误原因,并提供了有效的解决方案。

在Mac Mavericks系统上,我遇到了一个有趣的问题:一个简单的C++程序虽然可以使用clang++成功编译,但在尝试通过R CMD SHLIB构建并使用dyn.load在R中加载时却失败了。


此C++代码(保存在simple.cpp文件中)利用了Gurobi优化器:


#include "gurobi_c++.h"
#include

void fxn() {
GRBEnv env = GRBEnv(); // 创建Gurobi环境
GRBModel colgen = GRBModel(env); // 创建空模型对象
colgen.addVar(0, 1, 0.0, GRB_BINARY); // 向模型添加二进制变量
std::cout <<"Hello world" <}

int main(int argc, char **argv) {
fxn();
return 0;
}

使用clang++编译并运行此代码时,可以成功链接至Gurobi库:


$ clang++ simple.cpp -I/Library/gurobi562/mac64/include \
-L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
-stdlib=libstdc++ -lpthread -lm
$ ./a.out
Hello world

然而,使用R CMD SHLIB编译时虽然成功,但在R中加载生成的动态库时却出现了错误:


$ MAKEFLAGS="PKG_CXXFLAGS=-I/Library/gurobi562/mac64/include" R CMD SHLIB \
simple.cpp -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
-stdlib=libstdc++ -lpthread -lm
...
Error in dyn.load("simple.so") :
无法加载共享对象 '[路径]/simple.so':
dlopen([路径]/simple.so, 6): Symbol not found: __ZN8GRBModel6addVarEdddcNSt3__112basic_stringIcNS0_11char_traitsIcEENS0_9allocatorIcEEEE
引用自: [路径]/simple.so
预期在: 平坦命名空间
在 [路径]/simple.so

通过c++filt工具,我们可以看到缺失的符号是GRBModel::addVar(double, double, double, char, std::__1::basic_string, std::__1::allocator >),这应由Gurobi库提供。


通常,这类“符号未找到”的错误是因为没有正确链接所需的库。尽管我已成功编译并运行了simple.cpp,并且在使用R CMD SHLIB时传递了相同的链接选项,问题仍然存在。


经过进一步调查,我发现问题可能与编译代码时使用的-stdlib=libstdc++选项有关。移除此选项后,首次编译时就会出现链接错误,指出同样的未定义符号问题。


解决方案


#1


最终,我找到了解决方案,关键在于如何向R CMD SHLIB传递-stdlib=libstdc++选项。R CMD SHLIB会调用clang++两次,一次用于编译阶段生成对象文件(如simple.o),另一次用于链接阶段生成共享对象(如simple.so)。默认情况下,R CMD SHLIB仅在第二次调用时传递-stdlib=libstdc++选项,我们需要确保此选项也在第一次调用时生效。通过将-stdlib=libstdc++添加到PKG_CXXFLAGS中即可实现这一目标:


$ PKG_CXXFLAGS="-I/Library/gurobi562/mac64/include -stdlib=libstdc++" R CMD SHLIB \
simple.cpp -L/Library/gurobi562/mac64/lib -lgurobi_c++ -lgurobi56 \
-stdlib=libstdc++ -lpthread -lm
...

这样,dyn.load("simple.so")在R中就可以正常工作了。不过需要注意的是,为了能够从R中调用这些函数,还需要使用extern "C"或类似的方法暴露函数。


#2


另一个解决方案是调整函数的链接方式,因为R期望的是C链接而非C++链接。可以通过在函数声明前加上extern "C"来解决这一问题:


#include 

extern "C" void fxn() {
std::cout <<"Hello world" <}

然后使用如下命令进行编译和测试:


$ R --vanilla CMD SHLIB tmp.cpp && R --vanilla -e "dyn.load('tmp.so'); .C('fxn')"
...
> dyn.load('tmp.so'); .C('fxn')
Hello world
list()

推荐阅读
  • 本文探讨了如何通过预处理器开关选择不同的类实现,并解决在特定情况下遇到的链接器错误。 ... [详细]
  • 本教程涵盖OpenGL基础操作及直线光栅化技术,包括点的绘制、简单图形绘制、直线绘制以及DDA和中点画线算法。通过逐步实践,帮助读者掌握OpenGL的基本使用方法。 ... [详细]
  • 深入探讨栈和队列的应用实例——铁轨问题(Rails, ACM/ICPC CERC 1997, UVa 514)。该问题设定在一个城市火车站,涉及n节车厢从A方向驶入车站,并需按照特定顺序驶出B方向的铁轨。本文将通过算法实现来验证特定顺序的可行性。 ... [详细]
  • RTThread线程间通信
    线程中通信在裸机编程中,经常会使用全局变量进行功能间的通信,如某些功能可能由于一些操作而改变全局变量的值,另一个功能对此全局变量进行读取& ... [详细]
  • 在前两篇文章中,我们探讨了 ControllerDescriptor 和 ActionDescriptor 这两个描述对象,分别对应控制器和操作方法。本文将基于 MVC3 源码进一步分析 ParameterDescriptor,即用于描述 Action 方法参数的对象,并详细介绍其工作原理。 ... [详细]
  • UNP 第9章:主机名与地址转换
    本章探讨了用于在主机名和数值地址之间进行转换的函数,如gethostbyname和gethostbyaddr。此外,还介绍了getservbyname和getservbyport函数,用于在服务器名和端口号之间进行转换。 ... [详细]
  • 扫描线三巨头 hdu1928hdu 1255  hdu 1542 [POJ 1151]
    学习链接:http:blog.csdn.netlwt36articledetails48908031学习扫描线主要学习的是一种扫描的思想,后期可以求解很 ... [详细]
  • 本文探讨了如何在给定整数N的情况下,找到两个不同的整数a和b,使得它们的和最大,并且满足特定的数学条件。 ... [详细]
  • 使用GDI的一些AIP函数我们可以轻易的绘制出简 ... [详细]
  • 本文将深入探讨 Unreal Engine 4 (UE4) 中的距离场技术,包括其原理、实现细节以及在渲染中的应用。距离场技术在现代游戏引擎中用于提高光照和阴影的效果,尤其是在处理复杂几何形状时。文章将结合具体代码示例,帮助读者更好地理解和应用这一技术。 ... [详细]
  • 在iOS开发中,多线程技术的应用非常广泛,能够高效地执行多个调度任务。本文将重点介绍GCD(Grand Central Dispatch)在多线程开发中的应用,包括其函数和队列的实现细节。 ... [详细]
  • C语言编写线程池的简单实现方法
    2019独角兽企业重金招聘Python工程师标准好文章,一起分享——有时我们会需要大量线程来处理一些相互独立的任务,为了避免频繁的申请释放线程所带 ... [详细]
  • 我有一个从C项目编译的.o文件,该文件引用了名为init_static_pool ... [详细]
  • 基于Linux开源VOIP系统LinPhone[四]
    ****************************************************************************************** ... [详细]
  • 在尝试对 QQmlPropertyMap 类进行测试驱动开发时,发现其派生类中无法正常调用槽函数或 Q_INVOKABLE 方法。这可能是由于 QQmlPropertyMap 的内部实现机制导致的,需要进一步研究以找到解决方案。 ... [详细]
author-avatar
ciaos
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有