Python 2.7 将结构中的Python/C指针指向另一个结构

Python 2.7 将结构中的Python/C指针指向另一个结构,python-2.7,swig,robotics,Python 2.7,Swig,Robotics,我正在使用从C生成的Player/Stage SWIG代码,现在我正在尝试访问一个值指向另一个结构的结构。我想知道如何在python中提取结构数组 C代码如下所示: /** @brief Localization device data. */ typedef struct { /** Device info; must be at the start of all device structures. */ playerc_device_t info; /** Map dimen

我正在使用从C生成的Player/Stage SWIG代码,现在我正在尝试访问一个值指向另一个结构的结构。我想知道如何在python中提取结构数组

C代码如下所示:

/** @brief Localization device data. */
typedef struct
{
  /** Device info; must be at the start of all device structures. */
  playerc_device_t info;

  /** Map dimensions (cells). */
  int map_size_x, map_size_y;

  /** Map scale (m/cell). */
  double map_scale;

  /** Next map tile to read. */
  int map_tile_x, map_tile_y;

  /** Map data (empty = -1, unknown = 0, occupied = +1). */
  int8_t *map_cells;

  /** The number of pending (unprocessed) sensor readings. */
  int pending_count;

  /** The timestamp on the last reading processed. */
  double pending_time;

  /** List of possible poses. */
  int hypoth_count;
  player_localize_hypoth_t *hypoths;

  double mean[3];
  double variance;
  int num_particles;
  playerc_localize_particle_t *particles;

} playerc_localize_t;

/** @brief Hypothesis format.

Since the robot pose may be ambiguous (i.e., the robot may at any
of a number of widely spaced locations), the @p localize interface is
capable of returning more that one hypothesis. */
typedef struct player_localize_hypoth
{
  /** The mean value of the pose estimate (m, m, rad). */
  player_pose2d_t mean;
  /** The covariance matrix pose estimate (lower half, symmetric matrix) 
      (cov(xx) in m$^2$, cov(yy) in $^2$, cov(aa) in rad$^2$, 
       cov(xy), cov(ya), cov(xa) ). */
  double cov[6];
  /** The weight coefficient for linear combination (alpha) */
  double alpha;
} player_localize_hypoth_t;
(x, y, z) = PLN.get_waypoint(n)
python的代码是自动生成的。我试图访问hypoths变量中的元素,如何在python中实现这一点?我可以访问大多数变量。下面是生成的swig代码

class playerc_localize(_object):
    __swig_setmethods__ = {}
    __setattr__ = lambda self, name, value: _swig_setattr(self, playerc_localize, name, value)
    __swig_getmethods__ = {}
    __getattr__ = lambda self, name: _swig_getattr(self, playerc_localize, name)
    __repr__ = _swig_repr
    __swig_setmethods__["info"] = _playerc.playerc_localize_info_set
    __swig_getmethods__["info"] = _playerc.playerc_localize_info_get
    if _newclass:info = _swig_property(_playerc.playerc_localize_info_get, _playerc.playerc_localize_info_set)
    __swig_setmethods__["map_size_x"] = _playerc.playerc_localize_map_size_x_set
    __swig_getmethods__["map_size_x"] = _playerc.playerc_localize_map_size_x_get
    if _newclass:map_size_x = _swig_property(_playerc.playerc_localize_map_size_x_get, _playerc.playerc_localize_map_size_x_set)
    __swig_setmethods__["map_size_y"] = _playerc.playerc_localize_map_size_y_set
    __swig_getmethods__["map_size_y"] = _playerc.playerc_localize_map_size_y_get
    if _newclass:map_size_y = _swig_property(_playerc.playerc_localize_map_size_y_get, _playerc.playerc_localize_map_size_y_set)
    __swig_setmethods__["map_scale"] = _playerc.playerc_localize_map_scale_set
    __swig_getmethods__["map_scale"] = _playerc.playerc_localize_map_scale_get
    if _newclass:map_scale = _swig_property(_playerc.playerc_localize_map_scale_get, _playerc.playerc_localize_map_scale_set)
    __swig_setmethods__["map_tile_x"] = _playerc.playerc_localize_map_tile_x_set
    __swig_getmethods__["map_tile_x"] = _playerc.playerc_localize_map_tile_x_get
    if _newclass:map_tile_x = _swig_property(_playerc.playerc_localize_map_tile_x_get, _playerc.playerc_localize_map_tile_x_set)
    __swig_setmethods__["map_tile_y"] = _playerc.playerc_localize_map_tile_y_set
    __swig_getmethods__["map_tile_y"] = _playerc.playerc_localize_map_tile_y_get
    if _newclass:map_tile_y = _swig_property(_playerc.playerc_localize_map_tile_y_get, _playerc.playerc_localize_map_tile_y_set)
    __swig_setmethods__["map_cells"] = _playerc.playerc_localize_map_cells_set
    __swig_getmethods__["map_cells"] = _playerc.playerc_localize_map_cells_get
    if _newclass:map_cells = _swig_property(_playerc.playerc_localize_map_cells_get, _playerc.playerc_localize_map_cells_set)
    __swig_setmethods__["pending_count"] = _playerc.playerc_localize_pending_count_set
    __swig_getmethods__["pending_count"] = _playerc.playerc_localize_pending_count_get
    if _newclass:pending_count = _swig_property(_playerc.playerc_localize_pending_count_get, _playerc.playerc_localize_pending_count_set)
    __swig_setmethods__["pending_time"] = _playerc.playerc_localize_pending_time_set
    __swig_getmethods__["pending_time"] = _playerc.playerc_localize_pending_time_get
    if _newclass:pending_time = _swig_property(_playerc.playerc_localize_pending_time_get, _playerc.playerc_localize_pending_time_set)
    __swig_setmethods__["hypoth_count"] = _playerc.playerc_localize_hypoth_count_set
    __swig_getmethods__["hypoth_count"] = _playerc.playerc_localize_hypoth_count_get
    if _newclass:hypoth_count = _swig_property(_playerc.playerc_localize_hypoth_count_get, _playerc.playerc_localize_hypoth_count_set)
    __swig_setmethods__["hypoths"] = _playerc.playerc_localize_hypoths_set
    __swig_getmethods__["hypoths"] = _playerc.playerc_localize_hypoths_get
    if _newclass:hypoths = _swig_property(_playerc.playerc_localize_hypoths_get, _playerc.playerc_localize_hypoths_set)
    __swig_setmethods__["mean"] = _playerc.playerc_localize_mean_set
    __swig_getmethods__["mean"] = _playerc.playerc_localize_mean_get
    if _newclass:mean = _swig_property(_playerc.playerc_localize_mean_get, _playerc.playerc_localize_mean_set)
    __swig_setmethods__["variance"] = _playerc.playerc_localize_variance_set
    __swig_getmethods__["variance"] = _playerc.playerc_localize_variance_get
    if _newclass:variance = _swig_property(_playerc.playerc_localize_variance_get, _playerc.playerc_localize_variance_set)
    __swig_setmethods__["num_particles"] = _playerc.playerc_localize_num_particles_set
    __swig_getmethods__["num_particles"] = _playerc.playerc_localize_num_particles_get
    if _newclass:num_particles = _swig_property(_playerc.playerc_localize_num_particles_get, _playerc.playerc_localize_num_particles_set)
    __swig_setmethods__["particles"] = _playerc.playerc_localize_particles_set
    __swig_getmethods__["particles"] = _playerc.playerc_localize_particles_get
    if _newclass:particles = _swig_property(_playerc.playerc_localize_particles_get, _playerc.playerc_localize_particles_set)
    def __init__(self, *args): 
        this = _playerc.new_playerc_localize(*args)
        try: self.this.append(this)
        except: self.this = this
    def destroy(self): return _playerc.playerc_localize_destroy(self)
    def subscribe(self, *args): return _playerc.playerc_localize_subscribe(self, *args)
    def unsubscribe(self): return _playerc.playerc_localize_unsubscribe(self)
    def set_pose(self, *args): return _playerc.playerc_localize_set_pose(self, *args)
    def get_particles(self): return _playerc.playerc_localize_get_particles(self)
    __swig_destroy__ = _playerc.delete_playerc_localize
    __del__ = lambda self : None;
playerc_localize_swigregister = _playerc.playerc_localize_swigregister
playerc_localize_swigregister(playerc_localize)
一切都是用SWIG编译的,但现在我的python代码给出了错误。我知道alpha线可能是错误的,但两条线的错误相同:

LOC = playerc_localize(CON, 0)
if LOC.subscribe(PLAYERC_OPEN_MODE) != 0:
   raise playerc_error_str()

CON.read()
# This should work right? If I omit the index,
# then I get the first value from the array.
print LOC.get_hypoth(0).alpha
print LOC.get_hypoth(1)
我在python中遇到以下错误:

print LOC.get_hypoth(1).alpha
File "/usr/local/lib/python2.7/dist-packages/playerc.py", line 7413, in get_hypoth
return _playerc._playerc_localize_get_hypoth(self, index)
TypeError: in method '_playerc_localize_get_hypoth', argument 1 of type 'playerc_localize_t *'
第二部分 我遇到了另一个问题,我再次尝试访问一些值,但它不起作用,我无法找出哪里出了问题。我正在尝试访问planner设备中的航路点:

PLN = playerc_planner(CON, 0)
  if PLN.subscribe(PLAYERC_OPEN_MODE) != 0:
     raise playerc_error_str()
# saves the waypoints in PLN.waypoints
PLN.get_waypoints()
# gives: <Swig Object of type 'double (*)[3]' at 0x38105d0>
# if i try accessing members of it using (0) or [0] or something I get errors
print PLN.waypoints
playerc_wrap.i中的部分:

%header
%{
    #define new_playerc_planner playerc_planner_create
    #define del_playerc_planner playerc_planner_destroy
    typedef playerc_planner_t playerc_planner;
%}

typedef struct
{
  playerc_device info;
  int path_valid;
  int path_done;
  double px, py, pa;
  double gx, gy, ga;
  double wx, wy, wa;
  int curr_waypoint;
  int waypoint_count;
  double (*waypoints)[3];
    %extend
    {
        playerc_planner (playerc_client *client, int index);
        void destroy(void);
        int subscribe (int access);
        int unsubscribe (void);
        int set_cmd_pose (double gx, double gy, double ga);
        int get_waypoints (void);
        int enable (int state);
    }
} playerc_planner;
以及playerc_wrap.h中的相关部分:

typedef struct
{
  playerc_device_t info;
  int path_valid;
  int path_done;
  double px, py, pa;
  double gx, gy, ga;
  double wx, wy, wa;
  int curr_waypoint;
  int waypoint_count;
  double (*waypoints)[3];
} playerc_planner_t;

PLAYERC_EXPORT playerc_planner_t *playerc_planner_create(playerc_client_t *client, int index);
PLAYERC_EXPORT void playerc_planner_destroy(playerc_planner_t *device);
PLAYERC_EXPORT int playerc_planner_subscribe(playerc_planner_t *device, int access);
PLAYERC_EXPORT int playerc_planner_unsubscribe(playerc_planner_t *device);
PLAYERC_EXPORT int playerc_planner_set_cmd_pose(playerc_planner_t *device,
                                  double gx, double gy, double ga);
PLAYERC_EXPORT int playerc_planner_get_waypoints(playerc_planner_t *device);

PLAYERC_EXPORT int playerc_planner_enable(playerc_planner_t *device, int state);

因此,我再次迷失在如何访问这个双(*)[3]变量中的航路点上,我尝试了一些东西,但都无法在SWIG中编译。再次感谢

这些动态大小的数组似乎没有正确包装在libcplayer的SWIG接口文件中。
LOC.hypoths
访问器可能只给您数组中的第一个元素,而不是其他任何元素

我认为最简单的方法是向playerc.I添加类似的内容,并重新生成SWIG绑定:

%inline %{
  player_localize_hypoth_t *_playerc_localize_get_hypoth(playerc_localize *localize, int index)
  {
    return &(localize->hypoths[index]);
  }
%}

%extend playerc_localize {
  %pythoncode %{
    def get_hypoth(self, index):
        return _playerc._playerc_localize_get_hypoth(self, index)
  %}
}
然后您应该能够使用
LOC.get\u hypoth(n)
访问Python中的元素编号
n

参考资料:

注:

结构的名称是
playerc\u localize
而不是
playerc\u localize\u t
,因为
playerc\u swig\u parse.py
脚本将正则表达式应用于接口文件

第二部分 类似的问题。同样,可能有一种更聪明的方法可以做到这一点,但这种简单的方法既漂亮又干净,没有必要尝试使它变得比现在更复杂:

%inline %{
  double _playerc_planner_get_waypoint_coord(playerc_planner *planner, int index, int coord)
  {
    return planner->waypoints[index][coord];
  }
%}

%extend playerc_planner {
  %pythoncode %{
    def get_waypoint(self, index):
        x = _playerc._playerc_planner_get_waypoint_coord(self, index, 0)
        y = _playerc._playerc_planner_get_waypoint_coord(self, index, 1)
        z = _playerc._playerc_planner_get_waypoint_coord(self, index, 2)
        return (x, y, z)
  %}
}
然后,您应该能够访问Python中的航路点编号
n
,如下所示:

/** @brief Localization device data. */
typedef struct
{
  /** Device info; must be at the start of all device structures. */
  playerc_device_t info;

  /** Map dimensions (cells). */
  int map_size_x, map_size_y;

  /** Map scale (m/cell). */
  double map_scale;

  /** Next map tile to read. */
  int map_tile_x, map_tile_y;

  /** Map data (empty = -1, unknown = 0, occupied = +1). */
  int8_t *map_cells;

  /** The number of pending (unprocessed) sensor readings. */
  int pending_count;

  /** The timestamp on the last reading processed. */
  double pending_time;

  /** List of possible poses. */
  int hypoth_count;
  player_localize_hypoth_t *hypoths;

  double mean[3];
  double variance;
  int num_particles;
  playerc_localize_particle_t *particles;

} playerc_localize_t;

/** @brief Hypothesis format.

Since the robot pose may be ambiguous (i.e., the robot may at any
of a number of widely spaced locations), the @p localize interface is
capable of returning more that one hypothesis. */
typedef struct player_localize_hypoth
{
  /** The mean value of the pose estimate (m, m, rad). */
  player_pose2d_t mean;
  /** The covariance matrix pose estimate (lower half, symmetric matrix) 
      (cov(xx) in m$^2$, cov(yy) in $^2$, cov(aa) in rad$^2$, 
       cov(xy), cov(ya), cov(xa) ). */
  double cov[6];
  /** The weight coefficient for linear combination (alpha) */
  double alpha;
} player_localize_hypoth_t;
(x, y, z) = PLN.get_waypoint(n)

谢谢!如何从命令行重新生成SWIG绑定?或者只是重建播放器(然后它会自动构建SWIG绑定)嗯,我只是在playerc.I文件中复制粘贴了您的代码,但是我遇到了一些错误(更新了我原来的问题)。似乎玩家没有定义(或其他什么)。@DanFritz我在代码的第2行犯了一个错误。我已经更新了答案来修正错误。顺便说一句,我看不出player\u localize\u hypothh\t声明在哪个文件中?尝试了您的解决方案,仍然没有成功。我现在有一个不同的错误,更新了我原来的答案。player\u localize\u hypoth\t在player\u interfacegen自动生成的player\u interfaces.h中声明。py@DanFritz我修正了代码第4行的另一个错误,对此表示抱歉。显然,没有代码在我面前编译是一个障碍。如果你熟悉C语言,你也许可以自己修复我的错误,但不用担心。我也不清楚player\u localize\u hypoth\t是否被包装在Python绑定中,因此这可能是您想要克服的另一个问题。