我发现了这个问题,但一个答案基本上就是你不想这样做: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();
}
只有public void baz(){baz_internal(); ...}生成。 这里的问题是%rename和%typemap(javamethodmodifiers)是唯一的,因为范围是CLASS :: METHOD,但%typemap(javacode)适用于整个类。如果语法如
%typemap(javacode,append=true) { // code }
得到支持,然后这将解决问题。是否有一些技术可以实现这一目标?这对于像javacode或javaimports这样的默认值为空的类型图是有意义的。
答案 0 :(得分:1)
我可以创建一个SWIG宏来生成您正在寻找的代码。这有点像一个小屋,但它确实有效。诀窍是滥用javaout(使用noblock = 1)typemap而不是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
用于引用默认的,不太专业化的类型映射,以避免为非原始/特殊情况返回复制大量代码。
答案 1 :(得分:0)
以下是三个解决方案。将SOLUTION的定义更改为1、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; }
%}