我正在使用swig在c和java(android)之间创建一个粘合剂。
我在c中定义了一个类型boolean,使用如下:
(myglue.h)
typedef enum boolean {
TRUE = 0x1,
FALSE = 0x0
} Boolean;
Boolean booleanValue = TRUE;
Boolean isRunning() {
return booleanValue;
}
然后在Java中,我要执行以下操作:
if(MyGlue.isRunning) {
..do something..
}
我遇到的问题是myglue.isrunning返回一个int
我可以制作一个swig类型映射,将int转换为布尔值吗?
我尝试过以下操作,但没有完全掌握swig类型映射的用法:
在我的swig配置文件中添加了以下内容
%typemap(out) Boolean {
$result = boolean($1);
}
我没有得到我想要的,而且我不知道把从int到boolean like的转换放在哪里(返回值!=0)我想我需要指定类型映射中的某个位置。
有没有可能用swig来实现这种转换,以便在外部处理布尔值而不是int值?
最佳答案
您对类型映射的使用是正确的,实际上您可以使用in/out类型映射来完成这项工作,但是您还需要设置jstype/jnitype/jtype类型映射,以便更改生成方法的签名。
一般来说,对于java类型映射,有一个从c->jni intermediate->final java类型的转换。如果您自己编写一个类型映射,那么在“最终java类型”阶段完成它将是用最少的类型映射编写代码的最简单的地方。我给你举了一个例子。实际上,这意味着只更改javain、javaout和jstype类型映射:
%module test
%{
#include "test.h"
%}
%typemap(jstype) enum boolean "boolean"
%typemap(javacode) enum boolean %{
public boolean toBoolean() {
return this == TRUE;
}
%}
%typemap(javaout) enum boolean {
return $javaclassname.swigToEnum($jnicall).toBoolean();
}
%typemap(javain) enum boolean "($javainput?Boolean.TRUE:Boolean.FALSE).swigValue()"
%include "test.h"
这段代码确实有点冗长——javain类型映射可以简单地写成
$javainput?0:1
,javaout也可以类似地简单,完全不依赖swig生成的枚举。我这样写主要是为了展示它如何与更复杂的枚举进行交互。所以我们可以写:%module test
%{
#include "test.h"
%}
%typemap(jstype) enum boolean "boolean"
%typemap(javaout) enum boolean {
return $jnicall != 0;
}
%typemap(javain) enum boolean "$javainput?1:0"
%include "test.h"
它有硬编码的幻数,在这里总是有效的,因为您显式地给出了正好两个枚举成员值0和1,但是如果您不能100%确定这对于更一般的枚举包装总是正确的,可能会导致一些奇怪的错误。
我之前暗示过,我们可以编写类型映射,将其作为jboolean传递,从本机代码一直到用户使用的代理类。这是真的,并且不需要一个明显的类型转换,但是在现实中,我们可以借鉴现有的SWIG库支持C++cc>类型,甚至使用我们的自定义枚举。(这主要是因为来自
bool
>enum boolean
的c样式转换的工作方式与我们希望的0/1值一样)。所以我们可以简单地写下:
%module test
%{
#include "test.h"
%}
%apply bool { enum boolean };
%include "test.h"
它将
jboolean
类型映射复制到bool
类型映射中。如果出于任何原因,您确实想调整这些类型映射的某些/部分,那么您仍然可以将其作为执行此操作的基础,只需将所需内容更改为重要内容即可。(在这个阶段,我已经通过swig运行了上面的示例,并检查了输出,但没有编译输出,因为我现在没有一个jdk来正确地测试它)
底线:尝试所有三个建议,并查看生成的testjni.java、test.java和test_wrap.c文件,以了解每个类型映射对生成的代码有什么影响。