简体   繁体   English

Swig如何定义将C类型定义的布尔值转换为Java布尔值的类型图

[英]Swig how to define a typemap that converts a C typedefined Boolean to java boolean

I'm using swig to create a glue between C and Java (Android). 我正在使用Swig在C和Java(Android)之间创建胶水。 I have defined a type Boolean in C and used like this : (MyGlue.h) 我已经在C语言中定义了一个布尔类型,并且使用了这样的形式:(MyGlue.h)

typedef enum boolean {
    TRUE = 0x1,
    FALSE = 0x0
} Boolean;

Boolean booleanValue = TRUE;

Boolean isRunning() {
    return booleanValue;
}

Then in Java I want to do the following: 然后在Java中,我要执行以下操作:

if(MyGlue.isRunning) {
    ..do something..
}

the problem I have is that MyGlue.isRunning returns an int 我的问题是MyGlue.isRunning返回一个int

Can I make a swig typemap that converts an int to a boolean value? 我可以制作一个将Int转换为布尔值的Swig类型图吗?

I have tried the following, but I did not fully grasp the usage of a swig typmap: in my swig config file added the follwing 我尝试了以下操作,但是我没有完全掌握swig typmap的用法:在我的swig配置文件中添加了以下内容

%typemap(out) Boolean {
    $result = boolean($1);
}

I'm not getting what I want, besides I don't know where to put the conversion from int to boolean like (return_value != 0) that I suppose I need to specify somewhere in the typemap. 我没有得到我想要的东西,除了我不知道将从int转换为boolean之类的东西(return_value!= 0),我认为我需要在类型图中指定。

Is it possible to achieve this conversion with swig so externally I deal with booleans and not with ints? 是否有可能用swig来实现这种转换,所以在外部我处理布尔值而不是ints?

You're on the right track with the typemaps and in fact you could do it using in/out typemaps, but you'd also need to set the jstype/jnitype/jtype typemaps too in order to change the signature of generated methods. 您使用类型映射处于正确的轨道上,实际上您可以使用输入/输出类型映射来做到这一点,但是您还需要设置jstype / jnitype / jtype类型映射,以更改生成的方法的签名。

In general with Java typemaps there's a conversion from C->JNI intermediate->Final Java types. 通常,对于Java类型映射,从C-> JNI中间->最终Java类型进行了转换。 If you were to write a typemap yourself then doing it at just the "Final Java types" phase would be the simplest place to write code with fewest typemaps needed. 如果您要自己编写一个类型映射,那么只需在“最终Java类型”阶段进行操作,这将是编写代码所需的最少类型映射的最简单位置。 I've put together an example to show you what that's like. 我整理了一个例子,向您展示那是什么。 In practice it means changing just javain, javaout and jstype typemaps: 实际上,这意味着仅更改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"

This code is a little verbose really - the javain typemap could have been written as simply $javainput?0:1 and javaout could have been similarly simple instead of relying on the SWIG generated enum at all. 这段代码确实有点冗长-javain typemap可能被简单地写为$javainput?0:1而javaout可能同样简单,而不是完全依赖于SWIG生成的枚举。 I wrote it like that mostly just to show how it could interact with more complex enums. 我之所以这样写,主要是为了说明它如何与更复杂的枚举进行交互。 So we could have written: 所以我们可以这样写:

%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"

Which has hard-coded magic numbers that will always work here because you explicitly gave exactly two enum members values of 0 and 1, but if you aren't 100% certain that's always correct for more general enum wrapping could lead to some weird bugs. 它具有硬编码的幻数,在这里始终可用,因为您明确给了两个枚举成员值0和1,但是如果您不是100%确信对于更一般的枚举包装总是正确的,则可能会导致一些奇怪的错误。

I hinted earlier that we could write typemaps that pass it as a jboolean all the way from native code down to the proxy classes that users use. 之前我曾暗示过,我们可以编写类型映射,将其作为jboolean传递,从本机代码一直到用户使用的代理类。 That's true and would require no conversion of types along the way obviously, however in reality we can draw upon existing SWIG library support for the C++ bool type, even with our custom enum. 确实如此,并且显然不需要进行类型转换,但是实际上,即使使用我们的自定义枚举,我们也可以利用现有的SWIG库对C ++ bool类型的支持。 (This works mostly because the C style cast from enum boolean -> jboolean works as we'd hope for 0/1 values). (这之所以有效,主要是因为从enum boolean > jboolean为C的样式可以按我们希望的0/1值进行工作)。

So we can in fact simply write: 所以我们实际上可以简单地写:

%module test 

%{
#include "test.h"
%}

%apply bool { enum boolean };

%include "test.h"

Which copies the bool typemaps into enum boolean typemaps for us. 哪个将bool映射复制到我们的enum boolean映射中。 If for whatever reason you did want to tweak some/part of those typemaps you could still use that as a basis for doing this and just change what you needed to where it mattered. 如果您出于某种原因想要调整某些/部分类型映射,则仍可以将其用作执行此操作的基础,并且只需将需要的内容更改为重要的内容即可。

(At this stage I've run the above examples through SWIG and inspected but not compiled the output as I don't have a JDK to hand for testing it properly right now) (在这个阶段,我已经通过SWIG运行了以上示例,并检查了但未编译输出,因为我现在没有JDK可以正确测试它)

Bottom line: try all three suggestions and look at the generated testJNI.java, test.java and test_wrap.c files to understand what impact each typemap had on the generated code. 底线:尝试所有三个建议,并查看生成的testJNI.java,test.java和test_wrap.c文件,以了解每种类型映射对生成的代码有何影响。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM