使用 SWIG 和 Python/C API 包装返回 std::map 的函数

2024-03-26

我想包装一个 C++ 例程,它返回一个std::map整数和指向 C++ 类实例的指针。我在使用 SWIG 时遇到困难,希望能提供任何帮助。我试图通过一个简单的例子来将这个问题归结为它的本质。

标题test.h定义如下:

/* File test.h */
#include <stdlib.h>
#include <stdio.h>
#include <map>

class Test {
  private:
    static int n;
    int id;
  public:
    Test();
    void printId();
};

std::map<int, Test*> get_tests(int num_tests);

实现定义在test.cpp below:

/* File test.cpp */
#include "test.h"

std::map<int, Test*> get_tests(int num_tests) {
  std::map<int, Test*> tests;

  for (int i=0; i < num_tests; i++)
    tests[i] = new Test();

  return tests;
}

int Test::n = 0;

Test::Test() { 
  id = n;
  n++;
}

void Test::printId() { 
  printf("Test ID = %d", id); 
}

我写了一个SWIG接口文件test.i尝试适应这个例程,以便我可以返回std::map<int, Test*>作为 Python 中的字典:

%module test

%{
  #define SWIG_FILE_WITH_INIT
  #include "test.h"
%}

%include <std_map.i>
%typemap(out) std::map<int, Test*> {

  $result = PyDict_New();
  int size = $1.size();

  std::map<int, Test*>::iterator iter;
  Test* test;
  int count;

  for (iter = $1.begin(); iter != $1.end(); ++iter) {
    count = iter->first;
    test = iter->second;
    PyDict_SetItem($result, PyInt_FromLong(count),           
      SWIG_NewPointerObj(SWIG_as_voidptr(test), SWIGTYPE_p_Test, SWIG_POINTER_NEW | 0));
  }
}

%include "test.h"

我包装例程并编译 SWIG 生成的包装器代码,并将其链接为共享库,如下所示:

> swig -python -c++ -o test_wrap.cpp test.i
> gcc -c test.cpp -o test.o -fpic -std=c++0x
> gcc -I/usr/include/python2.7 -c test_wrap.cpp -o test_wrap.o -fpic -std=c++0x
> g++ test_wrap.o test.o -o _test.so -shared -Wl,-soname,_test.so

然后我希望能够在 Python 中执行以下操作:

import test

tests = test.get_tests(3)
print tests

for test in tests.values():
  test.printId()

如果我将其作为脚本运行example.py但是,我得到以下输出:

> python example.py 
{0: <Swig Object of type 'Test *' at 0x7f056a7327e0>, 1: <Swig Object of type 'Test *' at     
0x7f056a732750>, 2: <Swig Object of type 'Test *' at 0x7f056a7329f0>}
Traceback (most recent call last):
  File "example.py", line 8, in <module>
    test.printId()
AttributeError: 'SwigPyObject' object has no attribute 'printId'

任何想法为什么我得到SwigPyObject实例作为输出,而不是 SWIG 代理Test?任何帮助将不胜感激!


就目前情况而言,您看到的问题是由 SWIG 提供的 std_map.i 中的默认行为引起的。它提供尝试包装所有内容的类型映射std::map合理使用。

其中之一是干扰您自己的输出类型映射,因此如果我们将您的接口文件更改为:

%module test

%{
  #define SWIG_FILE_WITH_INIT
  #include "test.h"
%}

%include <std_map.i>
%clear std::map<int, Test*>;
%typemap(out) std::map<int, Test*> {

  $result = PyDict_New();
  int size = $1.size();

  std::map<int, Test*>::iterator iter;
  Test* test;
  int count;

  for (iter = $1.begin(); iter != $1.end(); ++iter) {
    count = iter->first;
    test = iter->second;
    PyObject *value = SWIG_NewPointerObj(SWIG_as_voidptr(test), SWIGTYPE_p_Test, 0);
    PyDict_SetItem($result, PyInt_FromLong(count), value);
  }
}

%include "test.h"

那么你的例子就有效了。这%clear抑制 std_map.i 中的默认类型映射,但保留定义本身。我不太清楚到底是什么导致了问题,无需更多挖掘,但您可以使用%template除非有充分的理由不这样做,否则可能会采用默认行为。

顺便说一句,你的电话:

SWIG_NewPointerObj(SWIG_as_voidptr(test), SWIGTYPE_p_Test, SWIG_POINTER_NEW | 0));

可能没有做你想要的 - 它将指针的所有权转移给Python,这意味着一旦Python代理完成它就会调用delete为您提供帮助,并在您的地图上留下一个悬空的指针。

您还可以使用$descriptor为了避免必须弄清楚 SWIG 的内部名称修改方案,所以它变成:

// No ownership, lookup descriptor:
SWIG_NewPointerObj(SWIG_as_voidptr(test), $descriptor(Test*), 0);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 SWIG 和 Python/C API 包装返回 std::map 的函数 的相关文章

随机推荐

  • Mongodb 聚合将参数传递给 $sample 的元素大小

    大家好 这里的任何人都可以帮助我解决以下问题 我想获得随机数量的测验列表 随机数将 以每节课为基础 问题是 mongodb 不允许将参数传递给 sample 的元素大小 任何人都可以给我解决方案 lessonModel aggregate
  • 如何知道所有设备令牌以循环发送推送通知(APNS)?

    我正在尝试使用 php 代码发送给下载我的 iPhone 应用程序的所有令牌 您能告诉我如何发送到多个设备以及如何进入设备令牌循环吗 这是我的代码
  • 将 bootstrap-slider 与 jQuery UI 结合使用

    我想用引导滑块 https github com seiyria bootstrap slider使用 jQuery UI 我按照文档并在加载 Bootstrap CSS 和 jQuery 后加载插件代码 但是 滑块尚未初始化
  • HG PUSH:中止:错误:现有连接被远程主机强制关闭

    我正在尝试推送我的变更集 在停止很长时间后 我收到以下错误消息 abort 错误 现有连接被远程主机强制关闭 我在 Windows 上使用 Apache 提前致谢 您是否配置了 http proxy 任何地方 例如 在你的 hgrc或乌龟m
  • 使用 Unity MVC5 进行依赖注入 - InjectionFactory 已弃用

    在最新版本的 Unity MVC5 中 InjectionFactory 已被弃用 以下是您在尝试使用它时会收到的过时警告 Obsolete InjectionFactory has been deprecated and will be
  • 在 iOS 7 中实现 heightForRowIndexPath:,但在 iOS 8 中使用编译时宏将其删除

    我想在 iOS 8 中实现新的自动调整表格视图单元格大小 同时保持对heightForRowAtIndexPath 在 iOS 7 中 问题是我必须删除方法覆盖heightForRowAtIndexPath 对于 iOS 8 但在 iOS
  • 如何使用 CSS 动态调整内容区域大小而不使用 JavaScript

    我想要的是这样的 当浏览器窗口调整大小时 蓝色区域也会调整大小 标题可见 蓝色区域从标题结束处开始 不是标题后面或上方 蓝色区域在页脚之前结束 蓝色区域和页脚之间存在 5 个黄色像素 这只能通过 CSS 和 HTML 实现 无需任何 jav
  • 如何从 Kendo 网格中删除所有行

    我在用Kendo grid 我想从中删除所有行Kendo grid using JavaScript 我使用 for 循环删除了它们 但我想找到删除所有行的最佳方法 尝试按照代码进行操作 var grid Grid data kendoGr
  • mongodb show dbs list数据库失败

    我是 mongodb 的新手 我刚刚在我的MAC上安装了mongoDB 看完这个 YouTube 视频后 在 mongo shell 中 我输入 show dbs 并得到有线输出 请帮助我理解并解决这个问题 gt show dbs 2017
  • 在 JDBC 中插入单引号以进行 SQL 查询不起作用

    我在通过 Oracle JDBC 在 JAVA 的准备好的语句中使用单引号时遇到了处理单引号的问题 假设我们有一张 Restaurant 表 其中一列 Restaurant name 的值为 1 Jack s Deli 我想使用一个简单的准
  • 使用另一个对话框的功能更改 jQuery-UI 对话框的标题

    为什么第二个 jQuery UI 对话框标题在弹出时不改变 第一个对话框我使用以下命令更改框的标题 attr title Confirm 它将第一个框的标题更改为 确认 就像它应该有的那样 现在 当第二个框弹出时 它应该将标题更改为 消息
  • 将 std::hash 专门化为依赖类型

    我已经定义了这个模板类结构 template
  • 尝试获取已安装应用程序列表时出现 TransactionTooLargeException

    作为我的应用程序的一部分 我通过使用 ApplicationPackageManager getInstalledApplications 获取设备上安装的应用程序列表 但对于某些用户 我收到崩溃报告说 android osBinderPr
  • 视图漂浮在所有 ViewController 之上

    在 iOS 上 视图是否可能始终漂浮在所有其他视图之上 我问这个是因为我想要实现的是一个漂浮在 ViewController 之上的视图 然后一个模态视图控制器滑入 同时该特定视图仍然漂浮在该模态视图控制器上 希望你明白我想说的 有 您可以
  • 程序员多久会被要求编写一个 makefile 文件? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 从当前文化中获取货币?

    有没有办法从应用程序文化设置动态获取当前信息 基本上 如果用户将文化设置为美国 我想知道货币是美元 或者如果他们将其设置为英国 我想知道英镑等 等等 这样我就可以在付款时将此信息发送给 PayPal 使用 RegionInfo ISOCur
  • 根据当前值更新 MongoDB 中的值

    我想做这样的事情 但是this关键字似乎没有在更新语句中设置 db items update foo set bar this foo false true 我必须使用eval来完成这个 是的 您不能引用修饰符中的其他字段 您必须使用 db
  • 使 MongoDB 中的表字段可文本搜索

    先决条件 已使用集合创建数据库posts它的架构如下 module exports function mongoose var Schema mongoose Schema var postSchema new Schema postID
  • Java TA-Lib 文档 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我正在寻找有关的文档TA Lib http www ta lib org index html在爪哇
  • 使用 SWIG 和 Python/C API 包装返回 std::map 的函数

    我想包装一个 C 例程 它返回一个std map整数和指向 C 类实例的指针 我在使用 SWIG 时遇到困难 希望能提供任何帮助 我试图通过一个简单的例子来将这个问题归结为它的本质 标题test h定义如下 File test h incl