热门标签 | 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()

推荐阅读
  • 深入理解Java泛型:JDK 5的新特性
    本文详细介绍了Java泛型的概念及其在JDK 5中的应用,通过具体代码示例解释了泛型的引入、作用和优势。同时,探讨了泛型类、泛型方法和泛型接口的实现,并深入讲解了通配符的使用。 ... [详细]
  • 从 .NET 转 Java 的自学之路:IO 流基础篇
    本文详细介绍了 Java 中的 IO 流,包括字节流和字符流的基本概念及其操作方式。探讨了如何处理不同类型的文件数据,并结合编码机制确保字符数据的正确读写。同时,文中还涵盖了装饰设计模式的应用,以及多种常见的 IO 操作实例。 ... [详细]
  • 本文详细介绍了Linux系统中信号量的相关函数,包括sem_init、sem_wait、sem_post和sem_destroy,解释了它们的功能和使用方法,并提供了示例代码。 ... [详细]
  • 本文介绍了如何在Linux系统中获取库源码,并在从源代码编译软件时收集所需的依赖项列表。 ... [详细]
  • 题目描述:给定n个半开区间[a, b),要求使用两个互不重叠的记录器,求最多可以记录多少个区间。解决方案采用贪心算法,通过排序和遍历实现最优解。 ... [详细]
  • IneedtofocusTextCellsonebyoneviaabuttonclick.ItriedlistView.ScrollTo.我需要通过点击按钮逐个关注Tex ... [详细]
  • 使用 Azure Service Principal 和 Microsoft Graph API 获取 AAD 用户列表
    本文介绍了一段通用代码示例,该代码不仅能够操作 Azure Active Directory (AAD),还可以通过 Azure Service Principal 的授权访问和管理 Azure 订阅资源。Azure 的架构可以分为两个层级:AAD 和 Subscription。 ... [详细]
  • 本文详细介绍了Java编程语言中的核心概念和常见面试问题,包括集合类、数据结构、线程处理、Java虚拟机(JVM)、HTTP协议以及Git操作等方面的内容。通过深入分析每个主题,帮助读者更好地理解Java的关键特性和最佳实践。 ... [详细]
  • XNA 3.0 游戏编程:从 XML 文件加载数据
    本文介绍如何在 XNA 3.0 游戏项目中从 XML 文件加载数据。我们将探讨如何将 XML 数据序列化为二进制文件,并通过内容管道加载到游戏中。此外,还会涉及自定义类型读取器和写入器的实现。 ... [详细]
  • MQTT技术周报:硬件连接与协议解析
    本周开发笔记重点介绍了在新项目中使用MQTT协议进行硬件连接的技术细节,涵盖其特性、原理及实现步骤。 ... [详细]
  • 本文详细介绍了如何构建一个高效的UI管理系统,集中处理UI页面的打开、关闭、层级管理和页面跳转等问题。通过UIManager统一管理外部切换逻辑,实现功能逻辑分散化和代码复用,支持多人协作开发。 ... [详细]
  • 本文详细解析了Python中的os和sys模块,介绍了它们的功能、常用方法及其在实际编程中的应用。 ... [详细]
  • 本文探讨了 Objective-C 中的一些重要语法特性,包括 goto 语句、块(block)的使用、访问修饰符以及属性管理等。通过实例代码和详细解释,帮助开发者更好地理解和应用这些特性。 ... [详细]
  • 本文探讨了 C++ 中普通数组和标准库类型 vector 的初始化方法。普通数组具有固定长度,而 vector 是一种可扩展的容器,允许动态调整大小。文章详细介绍了不同初始化方式及其应用场景,并提供了代码示例以加深理解。 ... [详细]
  • PHP 5.5.0rc1 发布:深入解析 Zend OPcache
    2013年5月9日,PHP官方发布了PHP 5.5.0rc1和PHP 5.4.15正式版,这两个版本均支持64位环境。本文将详细介绍Zend OPcache的功能及其在Windows环境下的配置与测试。 ... [详细]
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社区 版权所有