【问题标题】:Is it possible to add "text" to an existing typemap in swig?是否可以将“文本”添加到 swig 中的现有类型映射?
【发布时间】:2012-08-24 04:34:53
【问题描述】:

我发现了这个问题,但一个答案基本上是,你不想这样做:Is it possible to add code to an existing method when using Swig to build a C# wrapper for C++ code?

我实际上同意所描述的情况,即 OP 试图以一种可能很脆弱的方式插入代码。就我而言,我正在按照答案的建议做:重命名方法并使用 %typemap(javacode) 来实现包装方法。

但是我已经把它写成一个宏,我想重写几个方法,所以我最终多次调用 %typecode(javacode) ,只有最后一个包装方法 javacode typemap 是活动的。

宏的细节很复杂,因为它使用变量args来表达签名。

但证明问题:

%define WRAP(CLASS,METHOD)
%rename(method ## _internal,fullname=1) CLASS::METHOD;
%typemap(javamethodmodifiers) CLASS::METHOD "private";
%typemap(javacode) {
    public void METHOD() {
       METHOD ## _internal();  // delegate to original
       // extra code here
    }
}   // (note: dont use %{ %} -- need macro evaluation)
%enddef

WRAP(Foo,bar)
WRAP(Foo,baz)

class Foo {
   void bar();
   void baz();
}

只有公共 void baz() { baz_internal(); ... } 生成。 这里的问题是 %rename 和 %typemap(javamethodmodifiers) 是唯一的,因为 CLASS::METHOD 的范围,但 %typemap(javacode) 适用于整个类。如果语法像

 %typemap(javacode,append=true) {   // code   }

得到支持,那么这将解决问题。有没有什么技术可以做到这一点?这对于像 javacode 或 javaimports 这样的类型映射有意义,它们的默认值是空的。

【问题讨论】:

    标签: swig


    【解决方案1】:

    我可以制作一个 SWIG 宏来生成您正在寻找的代码。这有点麻烦,但它确实有效。诀窍是滥用 javaout (with noblock=1) 类型映射而不是 javacode,以便每个函数应用一次,而不是每个类应用一次:

    %module test
    
    %define WRAP(CLASS,METHOD)
    %rename(METHOD ## _internal,fullname=1) CLASS::METHOD;
    %javamethodmodifiers CLASS::METHOD "private";
    %typemap(javaout,noblock=1) void CLASS::METHOD {
      {
        $jnicall;
      }
    
      public void METHOD() {
        METHOD ## _internal();
        // some other bits
      }
    }
    %enddef
    
    WRAP(Foo,bar)
    WRAP(Foo,baz)
    
    class Foo {
    public:
       void bar();
       void baz();
    };
    

    这会生成您正在寻找的代码,但我怀疑您可以完全跳过%rename 并从 javaout 类型映射中完成所有操作。此方法适用于 SWIG 1.3 及更高版本。

    我确实尝试过使用$typemap 并复制类型映射的另一种方法,但最终没有成功。

    如果你想支持也返回东西的方法,你需要添加第三个宏参数:

    %define WRAP(CLASS,METHOD,RETURN)
    %rename(METHOD ## _internal,fullname=1) CLASS::METHOD;
    %javamethodmodifiers CLASS::METHOD "private";
    %typemap(javaout,noblock=1) RETURN CLASS::METHOD {
        $typemap(javaout,RETURN)
    
      public $typemap(jstype,RETURN) METHOD() {
        RETURN result = METHOD ## _internal();
        // some other bits
        return result;
      }
    }
    %enddef
    

    $typemap 用于引用默认的、不那么专业的类型映射,以避免为非原始/特殊情况返回重复大量代码。

    【讨论】:

    • 第一个解决方案有一个问题——委托方法是在内部 _internal 方法生成的。这可以通过切换到 %{ %} 并添加额外的 } 来解决。我担心这对我来说可能是个问题,因为我需要在里面调用宏。我会更多地玩这个 - 我不确定我是否完全理解 %{ %} 与 { } 在类型映射中的区别。
    • @Marvin - 当我用 2.0 和 1.3 测试它时,它对我来说工作正常。你能确认你使用的是什么版本的 SWIG 吗?你确定在类型图中有noblock=1 吗?如果我省略noblock=1,那么我会看到它在 _internal 方法中生成,否则没关系。 (pastebin.com/d5tmdanY 是我使用 SWIG2.0 和第一个样式得到的)。
    • 我剪切并粘贴了您的解决方案,它确实会生成带有开/关大括号的 bar_internal()... Swig 版本 2.0.5,但是... 另一个开发人员已经修补了我们的 java.cxx 版本就在这附近,我怀疑这就是区别所在。有趣的是,该补丁也可能被这种 javaout/delegation 方法所取代。
    【解决方案2】:

    以下是三种解决方案。将 SOLUTION 的定义更改为 1、2 或 3 以尝试它们中的每一个。

    • 解决方案 1 使用 SWIG-3.0.12 中添加的 %proxycode 功能,专门用于解决此问题。
    • 解决方案 2 使用默认类型映射方法的复制/粘贴/修改。这几乎就是类型映射的全部目的,即采用现有类型映射并对其进行自定义以获得所需的生成代码。
    • 解决方案 3 在用户类型映射中重复使用另一个(默认)类型映射的内容。
    %module example
    
    #define SOLUTION 1
    
    #if SOLUTION==1
    %define WRAP(CLASS,METHOD)
    %rename(METHOD ## _internal) CLASS::METHOD;
    %typemap(javamethodmodifiers) CLASS::METHOD "private";
    //%typemap(javacode) {
    %extend CLASS {
    %proxycode %{
      public void METHOD() {
         METHOD ## _internal();  // delegate to original
         // extra code here
        System.out.println("extra code in " + #METHOD + " SOLUTION 1");
      }
    %}
    }
    %enddef
    #elif SOLUTION==2
    %define WRAP(CLASS,METHOD)
    %typemap(javaout) void CLASS::METHOD {
        // Next line is copied from java.swg: %typemap(javaout) void
        $jnicall;
        // extra code here
        System.out.println("extra code in " + #METHOD + " SOLUTION 2");
      }
    %enddef
    #elif SOLUTION==3
    %define WRAP(CLASS,METHOD)
    %typemap(javaout) void CLASS::METHOD {
        // Next line re-uses/includes the typemap in java.swg: %typemap(javaout) void
        $typemap(javaout, void);
        // extra code here
        System.out.println("extra code in " + #METHOD + " SOLUTION 3");
      }
    %enddef
    #else
    #error "Bad SOLUTION"
    #endif
    
    WRAP(Foo,bar)
    WRAP(Foo,baz)
    
    %inline %{
    class Foo {
    public:
       void bar();
       void baz();
    };
    %}
    %{
    #include <iostream>
       void Foo::bar() { std::cout << "Foo::bar " << std::endl; }
       void Foo::baz() { std::cout << "Foo::baz " << std::endl; }
    %}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-10
      • 1970-01-01
      相关资源
      最近更新 更多