ImportError:在 python 中导入 swigged c++-class 时未定义的符号

Posted

技术标签:

【中文标题】ImportError:在 python 中导入 swigged c++-class 时未定义的符号【英文标题】:ImportError: undefined symbol when importing swigged c++-class in python 【发布时间】:2019-07-04 21:46:57 【问题描述】:

我尝试在 Python 中使用 c++ 类进行套接字通信。因此,我创建了一个使用nngpp 的类。将 swigged 文件导入 python 时,我得到 ImportError: undefined symbol: nng_msg_insert。类的定义是:

/* commclass.h */
#include <nngpp/nngpp.h>
#include <nngpp/protocol/req0.h>
#include <nngpp/protocol/rep0.h>
#include <nngpp/msg_body.h>
#include <nngpp/msg_header.h>
#include <nngpp/msg.h>
#include <nngpp/socket.h>
#include <nngpp/view.h>
#include <string>
#include <nlohmann/json.hpp>
//#include <thread>
#include <iostream>
#include <cstdio>
#include "/usr/local/include/nng/nng.h"
//#include <memory>
#include <chrono>
using json = nlohmann::json;

class CommIF

private:
    nng::socket socket;
    nng::msg message;
    int msg_size;
public:
    CommIF(const std::string option, std::string ipToListen, std::string ipToDial)
    
        message = nng::make_msg(0);
        if (option.compare("rep") == 0)
        
            socket = std::move(nng::rep::v0::open());
        
        else if (option.compare("req") == 0)
        
            socket = std::move(nng::req::v0::open());
        
        else
        
            printf("EXCEPTION");
        
        socket.listen(ipToListen.c_str());
        bool connected = false;
        while (connected == false)
        
            try
            
                socket.dial(ipToDial.c_str());
                connected = true;
                std::cout << "successfully connected\n";
            
            catch (const nng::exception &e)
            
                std::cerr << e.what() << "; retry in 1 s" << '\n';
                //std::this_thread::sleep_for(std::chrono::seconds(1));
            
        
        msg_size = 0;
    
;

swig的接口文件为:

/* commclass.i */
%module commclass
%
#include "src/commclass.h"
%
%include "src/commclass.h"

然后我从命令python3 build_commclass.py build_ext --inplace 开始构建过程。 build_commclass.py 文件如下

from distutils.core import setup, Extension
import os

name = "commclass"
version = "0.0.1"               
os.environ["CC"] = "g++"

setup(name = name, version = version, ext_modules = [Extension(
name = '_commclass', 
sources = ["commclass.i"],#"src/commclass.h"],
include_dirs = ['src'],#'/home/user1/Documents/extLibs','/usr/local/include'],
swig_opts = ["-c++", "-modern"]
)])

当我现在将类导入 python 时,我得到了上面提到的错误。我在 google 和 *** 上搜索了很多,我很确定这是一个链接器问题。我还用 distutils.core 的编译器和链接器选项尝试了很多不同的东西,但我没有找到解决方案。

编辑 1: 我现在将接口文件更改如下

/* commclass.i */
/* module*/
%module commclass
%
#include "/usr/local/include/nng/nng.h"
#include "src/nngpp/nngpp.h"
#include "src/nngpp/protocol/req0.h"
#include "src/nngpp/protocol/rep0.h"
#include "src/nngpp/socket.h"
#include "src/nngpp/msg.h"
#include "src/nngpp/aio.h"
#include "src/nngpp/aio_view.h"
#include "src/nngpp/msg_body.h"
#include "src/nngpp/msg_header.h"
#include "src/commclass.h"
%
%include "/usr/local/include/nng/nng.h"
%include "src/commclass.h"

我现在在 python 中导入时遇到同样的错误,但是未定义的符号发生了变化。现在是nng_aio_set_iovnng_msg_insertnng_aio_set_iov 都在我现在包含的文件 nng.h 中定义。我现在很困惑。

【问题讨论】:

【参考方案1】:

SWIG 默认只为%include 直接指定的定义生成接口。 nng_msg_insert 未在 src/commclass.h 中定义。您需要额外的 %include 语句来引入定义。

请注意,您可以将默认值更改为使用-includeall SWIG 标志递归到所有#include 语句,但您通常不希望整个&lt;iostream&gt;&lt;cstdio&gt;&lt;string&gt; 等接口如果没有额外的努力,它可能无法工作。

【讨论】:

以上是关于ImportError:在 python 中导入 swigged c++-class 时未定义的符号的主要内容,如果未能解决你的问题,请参考以下文章

ImportError:在 python 中导入 swigged c++-class 时未定义的符号

在 Django 中导入 python 模块时出错

ImportError:在使用 cx_Freeze 冻结的应用程序中导入 win32clipboard 时,DLL 加载失败

如何在 Python 中导入 pytraj?

ImportError:无法在 IPython 中导入名称“SparkContext”

无法在python中导入beautifulsoup