gpt4 book ai didi

python - 使用 SWIG 包装调用另一个对象成员函数的 C++ 类

转载 作者:行者123 更新时间:2023-11-27 23:09:31 25 4
gpt4 key购买 nike

我正在使用 swig 编写一个包装器到 c++ 类,以便与 python 一起使用。

当我尝试做 from CSMPy import * (CSMPy 是我的模块)我收到这条消息:

ImportError: dlopen(/Users/MUL_mac2/anaconda/lib/python2.7/site-packages/_CSMPy.so, 2): Symbol not found: __ZN4csmp4VSetILm2EE6ResizeERKSt5dequeIiSaIiEERKS2_ImSaImEESA_m
Referenced from: /Users/MUL_mac2/anaconda/lib/python2.7/site-packages/_CSMPy.so
Expected in: dynamic lookup

一些背景知识:

我有一个接口(interface)文件,其中包含一个包含我的包装器类的头文件:

这个类有一个对象作为私有(private)成员。

然后我想传递一些 std::deque<int> 类型的对象到成员函数这个对象像这样:this->object.Function(int_deque_a,int_deque_b)其中 object是我使用 swig 包装的类的成员。

当我评论上面的行时,一切都像一个魅力。我传递的所有容器都是传递给此对象成员函数的有效数据类型,并包含正确数量的条目。

一切都会编译,这只会在导入模块时发生。

我在这里错过了什么?

我正在使用 distutils 通过 python setup.py install 进行编译

设置.py:

CSMPy_module = Extension('_CSMPy',
include_dirs = [Bunch of include directories here],
library_dirs = ['MyLibraryPath'],
libraries = ['MyLibrary'],
sources=['CSMPy_wrap.cxx', 'WrapperClass.cpp'],
)
setup (name = 'CSMPy',
version = '0.1',
author = "My name",
description = """Simple Test""",
ext_modules = [CSMPy_module],
py_modules = ["CSMPy"],
)

MyLibrary 是一个静态库。

编辑 1:我正在为您提供我可以向所有人展示的代码版本

设置.h

#include <iostream>
#include <vector>
#include <deque>

#include "VSet.h"


class Setup {
public:
Setup();
~Setup();

void InitializeSetup();

private:

std::deque<size_t> npes;
std::deque<size_t> epes;

std::deque<std::vector<size_t> > eni; //plist
std::deque<std::vector<csmp::int32> > enb; //pfverts
std::deque<std::vector<csmp::double64> > ncl; //pelmt
std::map<size_t, csmp::int32> bnf; //bflags

std::deque<csmp::int32> et;
csmp::VSet<2U> v;
};

安装程序.cpp

#include "Setup.h"


Setup::Setup() {

std::cout<<"Setup initialized."<<std::endl;

}

Setup::~Setup() {

}

void Setup::InitializeSetup() {


for(size_t i = 0; i < this->eni.size(); i++) {

this->npes.push_back(this->eni[i].size());
}

for(size_t i = 0; i < this->enb.size(); i++) {

this->epes.push_back(this->enb[i].size());

}
this->v.Resize(this->et, npes, epes, this->ncl.size()); //This is the line that does not work
}

CSMPy.i

%module CSMPy

%{
#define SWIG_FILE_WITH_INIT
#include "stdlib.h"
#include <vector>
#include <deque>
#include <map>
#include "VSet.cpp"
#include "Setup.h"
#include "Number_Types.h"
%}

%include "Number_Types.h"

%include "std_map.i"
%include "std_vector.i"
%include "std_deque.i"

// Instantiate templates used by CSMPy
namespace std {
%template() pair<size_t, csmp::int32>;
%template() pair<size_t, csmp::double64>;

%template() pair<size_t, vector<size_t> >;
%template() pair<size_t, vector<csmp::int32> >;
%template() pair<size_t, vector<csmp::double64> >;

%template(Deque_SizeT) deque<size_t>;
%template(Deque_Int) deque<csmp::int32>;

%template(Vector_SizeT) vector<size_t>;
%template(Vector_Int32) vector<csmp::int32>;
%template(Vector_Double64) vector<csmp::double64>;

%template(Deque_Double64) deque<csmp::double64>;

%template(Deque_Vector_Int) deque<vector<csmp::int32> >;
%template(Deque_Vector_SizeT) deque<vector<size_t> >;
%template(Deque_Vector_Double64) deque<vector<csmp::double64> >;

%template(Map_SizeT_Int) map< size_t, csmp::int32>;
%template(Map_SizeT_Double64) map< size_t, csmp::double64>;

%template(Map_SizeT_Vector_SizeT) map< size_t, vector<size_t> >;
%template(Map_SizeT_Vector_Int) map< size_t, vector<csmp::int32> >;
%template(Map_SizeT_Vector_Double64) map< size_t, vector<csmp::double64> >;
}
%include "Setup.h"

编辑 2:

我做了 nm -gC myLib.so

我发现了这个回声

__ZN4csmp4VSetILm2EE6ResizeERKNSt3__15dequeIiNS2_9allocatorIiEEEERKNS3_ImNS4_ImEEEESC_m

c++ tilt 告诉我:

csmp::VSet<2ul>::Resize(std::__1::deque<int, std::__1::allocator<int> > const&, std::__1::deque<unsigned long, std::__1::allocator<unsigned long> > const&, std::__1::deque<unsigned long, std::__1::allocator<unsigned long> > const&, unsigned long)

关于这一点的几个注意事项,我已经切换到使用 clang++ 作为我的编译器并手动编译。我还在我的 .i 文件中放入了#include "VSet.cpp"。 (请参阅上一篇文章中的编辑)

我现在在 python 中导入时遇到此错误:

Symbol not found: __ZN4csmp5VData6InTextERSt14basic_ifstreamIcSt11char_traitsIcEE
Referenced from: ./_CSMPy.so
Expected in: flat namespace

我还创建了一个 main,它将实例化该对象,并且对 Initialize() 的调用有效。

最佳答案

找不到符号

__ZN4csmp4VSetILm2EE6ResizeERKSt5dequeIiSaIiEERKS2_ImSaImEESA_m

在 .so 中。感谢 Dave 对它进行了分解,我们现在知道它指的是

csmp::VSet<2ul>::Resize(
const std::deque<int>&,
const std::deque<unsigned long> &,
const std::deque<unsigned long> &)

因此,根据您发布的内容,您有两种类型的双端队列有点奇怪。

这里有一些尝试:

  1. 验证您的 _CSMP.so 链接到编译器附带的 STL 库,您可能必须在 setup.py 中指定一个额外的开关或字段。你说,当 Resize 不存在时,你的代码可以工作,所以这不太可能是问题所在。
  2. 在 setup.py 中打开详细输出,以便您可以看到编译和链接命令行参数
  3. 确保在 SWIG .i 文件中包含 %include std_deque.i。您没有收到编译错误,所以这不太可能是问题所在。
  4. 验证你已经实例化了你的deque<int>%template(IntDeque) std::deque<int>在你的 .i 中,因为 Python 对 C++ 模板一无所知,模板不是类,而是一个配方,因此编译器可以为你创建一个类。如果您确实同时使用 int 和 unsigned long,则必须实例化两者。我在您的代码中只看到 int 和 size_t。您不能假设 size_t 与 unsigned long 相同。
  5. 确认您的 DLL 包含 unsigned int 的此 Resize 方法的实例化。在你的 C++ 代码中。我认为您定义了 size_t 版本,或者 unsigned long 是意外的吗?

关于#5:

SWIG 生成 header 和源文件。在 header 中,它放置了遵循 Python C API 的函数并将它们注册到 Python 解释器中,在这些函数的主体中,它确定要从您的库中调用哪些 C/C++ 函数。在 DLL 中找不到上述 Resize 的事实表明 SWIG 认为需要重载 Resize,因此从它生成的函数中调用它,但您的 C++ 库没有实例化它。

这怎么可能?在您的 C++ 库中,您有一个带有 Resize 方法的类模板。类模板的技巧是编译器只会为 DLL 中使用的方法生成代码(所以如果你的类定义了 5 个方法但你的 DLL 只使用了 1 个,它不会为其他 4 个方法生成代码), 除非 如果您在库中显式实例化模板。你可以通过声明来做到这一点

template class VSet<2ul>; 

(无论 2ul 代表什么)在您的 C++ DLL 中,或通过 .i 文件中的 %template 指令的包装器 DLL。这将实例化 VSet<2ul> 的所有方法。 ,所以 Resize 也会在那里。 IF 这样生成的 Resize 有参数 deque<int>deque<unsigned long> .您的代码表明您假设 size_t 是无符号整数。如果 size_t 类型定义为 unsigned int,SWIG 应该能够处理它,但可能存在错误。最好不要假设。您可以为 unsigned int 添加一个 Resize 重载。或者您可以在安装程序中创建一个内联扩展方法,采用两个 unsigneld long deques 并调用 size_t 版本。有点像

%template DequeULong std::deque<unsigned long>

%extend Setup {
void Resize(const DequeInt& a, const DequeULong& b)
{
DequeSizet c;
... copy b into a DequeSizet
Resize(a, c);
}
}

关于python - 使用 SWIG 包装调用另一个对象成员函数的 C++ 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21198964/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com