带SWIG接口的for_each预处理器 [英] Preprocessor for_each witin SWIG interface

查看:63
本文介绍了带SWIG接口的for_each预处理器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在使用这个答案 REFLECTABLE 宏>在我的C ++头文件中,如下所示:

  #ifndef TIMER_H 
# define TIMER_H

//从链接的问题开始,但是(故意)在这里被SWIG忽略,
//唯一相关的是它为其他预处理器定义了REFLECTABLE
#include reflection.hh

struct Timer {
REFLECTABLE(
(float)startTime,
(float)endTime,

} ;

#endif

SWIG预处理器不会跟随 #include ,并且无论如何都不处理链接问题中的REFLECTABLE的定义,因此我的计划是完全忽略该问题,并用更合适的SWIG特定的REFLECTABLE定义代替。



我的目标是 SWIG预处理器扩展Timer,好像没有什么特别的事情发生,即:

  struct Timer {
float startTime;
浮动结束时间;
};为此,我写了一个简单的反射。i对该递归调用<$ c进行了简单的写法。i

$ c>%define SWIG宏:

  #define REM( ...)__VA_ARGS__ 
#定义对(x)REM x

%定义EXPAND(tail,...)
PAIR(tail);
EXPAND(__ VA_ARGS__)
%enddef

#define REFLECTABLE(...)EXPAND(__ VA_ARGS__)

我可以在test.i中使用:

 %module test 

%include reflection.i
%include timer.h

当我们运行 swig -python -Wall -E test.i 来检查通过SWIG预处理程序运行它的结果时,几乎可以,但是递归末尾的定义与我想要的不完全匹配:

  struct Timer {
/*@SWIG:reflection.i,4,EXPAND@*/
float startTime;
/*@SWIG:reflection.i,4,EXPAND@*/
浮动结束时间;
扩展
};

问题是递归被裸词 EXPAND ___ VA_ARGS __ 为空时的$ c>。我从此答案中使用了map.h,但这不适用于SWIG预处理器。



如何修改 REFLECTABLE 的定义,以便SWIG预处理程序仅生成我要查找的平面结构? / p>

解决方案

最后我想出了一个需要进行两项更改的解决方案:


  1. 还有更多的递归间接性,我们将两个令牌粘贴在一起以获得令牌 EXPAND_STOP EXPAND_MORE ,具体取决于 __ VA_ARGS __ 在此评估期间是否为空。进行此选择是因为SWIG评估

      #define STOP(...)更多

    更多,当有参数时,如无参数则简单地为STOP。 / p>

    然后, TOKEN 宏添加令牌粘贴运算符起作用所需的间接寻址。


  2. 对于 EXPAND_MORE EXPAND_STOP 都有一个虚假的第一个参数,可防止阻止我们吃掉没有参数的 EXPAND_STOP 的行为。




  #define REM(...)__VA_ARGS__ 
#define PAIR(x)REM x

#定义TOKEN_(x,y)x ## y
#定义TOKEN(x,y)TOKEN_(x,y)

#定义STOP(...)更多

%定义EXPAND_MORE(假,...)
EXPAND(__ VA_ARGS__)
%enddef

#定义EXPAND_STOP(假,...)

%定义EXPAND(tail,...)
PAIR(tail);
令牌(EXPAND_,STOP(__ VA_ARGS__))##(fake,## __ VA_ARGS__)
%enddef

#define REFLECTABLE(...)EXPAND(__ VA_ARGS__)

虽然可能不是最优雅的解决方案,但已经过测试并可以与SWIG 3.0.2。一起使用。


I've been using the REFLECTABLE macro from this answer in my C++ header file, which looks like:

#ifndef TIMER_H
#define TIMER_H

// From the linked question, but (deliberately) ignored by SWIG here, 
// only relevant is as much as it defines REFLECTABLE for other preprocessors
#include "reflection.hh"

struct Timer {
  REFLECTABLE (
    (float) startTime,
    (float) endTime,
  )
};

#endif

The SWIG preprocessor doesn't follow #include and doesn't handle the definition of REFLECTABLE from the linked question anyway, so my plan is to ignore that entirely and replace it with a more appropriate SWIG specific definition of REFLECTABLE.

My goal is for the SWIG preprocessor to expand Timer as though there was nothing special going on, i.e.:

struct Timer {
  float startTime;
  float endTime;
};

To that end I have written a simple reflection.i that makes a recursive call to a %define SWIG macro:

#define REM(...) __VA_ARGS__
#define PAIR(x) REM x

%define EXPAND(tail, ...)
  PAIR(tail);
  EXPAND(__VA_ARGS__)
%enddef

#define REFLECTABLE(...) EXPAND(__VA_ARGS__)

That I can use in test.i:

%module test

%include "reflection.i"
%include "timer.h"

When we run swig -python -Wall -E test.i to inspect the result of running this through the SWIG preprocessor it almost works, but the definition at the end of recursion doesn't quite match what I'd like:

struct Timer {
  /*@SWIG:reflection.i,4,EXPAND@*/
  float startTime;
  /*@SWIG:reflection.i,4,EXPAND@*/
  float endTime;
  EXPAND
};

The problem is that recursion gets terminated by the bareword EXPAND when ___VA_ARGS__ is empty. I looked at using map.h from this answer, but that also doesn't work with the SWIG preprocessor.

How can I modify my definition of REFLECTABLE so that the SWIG preprocessor just generates the flat structure I'm looking for?

解决方案

I came up with a solution in the end that required two changes:

  1. There's more indirection to the recursion, we paste two tokens together to get the token EXPAND_STOP or EXPAND_MORE, depending on whether or not the __VA_ARGS__ is empty during this evaluation. This selection takes place because SWIG evaluates

    #define STOP(...) MORE
    

    as MORE when there are arguments, but simply as STOP when there are no arguments.

    The TOKEN macro then adds the required indirection for the token paste operator to work.

  2. There's a fake first argument to both EXPAND_MORE and EXPAND_STOP that prevents the same behaviour from stopping us eating the call to EXPAND_STOP with no arguments.

#define REM(...) __VA_ARGS__
#define PAIR(x) REM x

#define TOKEN_(x,y) x##y
#define TOKEN(x,y) TOKEN_(x, y)

#define STOP(...) MORE

%define EXPAND_MORE(fake, ...)
  EXPAND(__VA_ARGS__)
%enddef

#define EXPAND_STOP(fake, ...)

%define EXPAND(tail, ...)
  PAIR(tail);
  TOKEN(EXPAND_,  STOP(__VA_ARGS__)) ## (fake, ##__VA_ARGS__)
%enddef

#define REFLECTABLE(...) EXPAND(__VA_ARGS__)

Although possibly not the most elegant solution this is tested and working with SWIG 3.0.2.

这篇关于带SWIG接口的for_each预处理器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆