使用 bjam 编译的来自 C++ 的未定义符号

Posted

技术标签:

【中文标题】使用 bjam 编译的来自 C++ 的未定义符号【英文标题】:Undefined symbol from C++ compiled using bjam 【发布时间】:2018-05-03 13:24:47 【问题描述】:

我有一个通过 Boost Python 与 C++ 交互的 Python 应用程序。应用程序的 C++ 部分是使用 Bjam 构建的(Bjam make 文件可以在问题的底部找到)。 C++ 编译(并且似乎链接)很好。

Python 执行后不久,它会抱怨从 C++ 文件引用的未定义符号。此 C++ 文件包含一个 C++ 标头,其中声明了未定义的符号。如果我删除对有问题的变量的引用,代码将继续正常执行。

如果我在库上运行 nm,它会列出带有 U(未定义)的符号。

有人可以帮助我为什么收到这个未定义的符号运行时错误吗?我认为这可能是因为我的 gcc 路径中没有包含某些内容?

python代码调用了一个C++方法,该方法使用C_NAMESPACE中定义的变量创建一个对象:

/dir/folder1/bridge.cpp

#include "c.h"

namespace CPP

    void calledByPython()
    
        MyClass x(C_NAMESPACE::VAR);
        // continues
    

位于头文件c.h中:

/dir/folder2/c.h

#ifndef C_H
#define C_H

namespace C_NAMESPACE

    extern const std::string VAR;

源文件的样子:

/dir/folder2/c.cpp

#include "c.h"

namespace

    const std::string VAR = "something";

我正在使用 bjam 构建这个 C++:

import python ;

lib gbclientlib : : <name>gbclient <search>$(gbclient_dir)/lib <link>static  ;
explicit gbclientlib ;  

project gb
  : requirements
        <location>. 
        <cxxflags>"-std=c++11 -Wno-deprecated -I /dir/folder1/ -I /dir/folder2/"
;

python-extension _bridge : bridge.cpp ;

【问题讨论】:

@AndyG 嗨,安迪,对不起,你能改写一下吗?我没有完全理解。 @AndyG 为什么 C 在这种情况下很重要?只是 Python 和 C++? @AndyG 啊,所以你的意思是 extern "C" const std::string VAR; ? 不幸的是,这不起作用:(问题当然不是 Python 访问 C++,而是 C++ 共享库在符号名称旁边包含一个“U”? 安迪你的传奇,你能把它作为答案,我会接受吗?干杯, 【参考方案1】:

当 C++ 代码被编译时,名称会被破坏。 C 代码不会被破坏。 C++ 名称修改给暴露函数带来了问题......真的在任何地方。

该问题的解决方案是将 C++ 调用封装在类似 C 的接口下,这样名称就不会被破坏。例如,要将您的 std::string VAR 返回给 C(最终是 Python):

extern "C"

   const char* get_var(void) return VAR.c_str();

Boost.Python 知道这一切,并试图通过使用 BOOST_PYTHON_MODULE 等宏隐藏外部“C”位来使事情变得更容易

extern "C" 技巧主要用于将 C++ 代码暴露给其他语言。 (不过,C# 有 CLR 和 PInvoke)

【讨论】:

以上是关于使用 bjam 编译的来自 C++ 的未定义符号的主要内容,如果未能解决你的问题,请参考以下文章

标头包含标准 C++ 库后的未定义符号

编译时错误“架构 x86_64 的未定义符号”是啥意思?

编译时 x86_64 的未定义符号

libcvd - 编译 C++ 时对“x ...”的未定义引用

使用 g++ 时 HDF5 的未定义符号

typedef和模板的未定义符号? [复制]