使用 -DSWIGWORDSIZE64 时,SWIG Java 将 int64_t 转换为 jlong
SWIG Java convert int64_t to jlong when using -DSWIGWORDSIZE64
上下文
我有一个带有重载 int
和 int64_t
的 C++ 代码,我需要将其包装到 Java
#include <cstdint>
int foo(int param);
int foo(int64_t param);
};
还有这一口
%{
#include <cstdint>
%}
%include "stdint.i"
%include "typemaps.i"
%ignore "";
%rename ("foo") foo(int);
%rename ("foo") foo(int64_t);
%include "foo.hpp";
海湾合作委员会
使用 GCC 时 int64_t 将被定义为 long int
grepc -rn "typedef.*INT64_TYPE" /lib/gcc
/lib/gcc/x86_64-linux-gnu/9/include/stdint-gcc.h:43:typedef __INT64_TYPE__ int64_t;
然后
gcc -dM -E -x c++ /dev/null | grep __INT64
#define __INT64_TYPE__ long int
所以我使用 -DSWIGWORDSIZE64
来避免 wrapper 类型错误的问题
grep "int64" -C 1 /usr/local/share/swig/4.0.1/stdint.i
#if defined(SWIGWORDSIZE64)
typedef long int int64_t;
#else
typedef long long int int64_t;
#endif
到目前为止还不错(至少在 python 和 csharp 中),但是在 Java...
痛饮Java
in Java SWIG swig 似乎将 C++ long int
包装到 C Wrapper int
(也将 2^64 截断为 2^32...)
参考:http://www.swig.org/Doc4.0/SWIGDocumentation.html#Java_default_primitive_type_mappings
来源:https://github.com/swig/swig/blob/master/Lib/java/typemaps.i
所以这两种方法将具有相同的原型 -> 我当前的问题
AFAIK java/typemaps.i nor java.swg 支持 SWIGWORDSIZE64
开关...
测试协议
重现问题(我使用的是 swig 4.0.1)
mkdir -p gen
swig -DSWIGWORDSIZE64 -I. -c++ -java -o gen/foo_java_wrap.cc -package com.google.Foo -module main -outdir gen foo.i
观察到
foo.hpp:9: Warning 516: Overloaded method baz(int64_t) ignored,
foo.hpp:8: Warning 516: using baz(int) instead.
cat gen/main.java
...
package com.google.Foo;
public class main {
public static int baz(int param) {
return mainJNI.baz__SWIG_0(param);
}
}
预计
cat gen/main.java
...
package com.google.Foo;
public class main {
public static int baz(int param) {
return mainJNI.baz__SWIG_0(param);
}
public static int baz(long param) {
return mainJNI.baz__SWIG_1(param);
}
}
那么我该如何处理这个问题呢?
谢谢
编辑:你可以在这里找到这个例子:https://github.com/Mizux/swig_java
(ed可以点徽章看logs/files)
一个丑陋的解决方法是不使用SWIGWORDSIZE64
,因此int64_t
将被定义为long long
将被映射为 jlong
。
参见:http://www.swig.org/Doc4.0/SWIGDocumentation.html#Java_default_primitive_type_mappings
BUT,在 C++ 扭曲文件中,您将有一些 long long
需要修补(例如使用 post 进程 sed -i -e 's/long long/int64_t/g'
) 否则编译失败,因为 long long
与 int64_t
(又名 long int
)
不是同一类型
您可以尝试提供自己的类型映射。
%include "stdint.i;"
#ifdef SWIGWORDSIZE64
%define PRIMITIVE_TYPEMAP(TYPE, JNITYPE, JTYPE)
%clear TYPE;
%typemap(jstype) TYPE "JTYPE";
%typemap(javain) TYPE "$javainput";
%typemap(jtype) TYPE "JTYPE";
%typemap(jni) TYPE "JNITYPE";
%typemap(in) TYPE %{ = (_ltype)&$input; %}
%typemap(freearg) TYPE "";
%typemap(out) TYPE %{ $result = ; %}
%typemap(javaout) TYPE %{ return $jnicall; %}
%enddef // PRIMITIVE_TYPEMAP
PRIMITIVE_TYPEMAP(long int, jlong, long);
PRIMITIVE_TYPEMAP(unsigned long int, jlong, long);
#undef PRIMITIVE_TYPEMAP
#endif // SWIGWORDSIZE64
因为您想重用 long long
类型映射:
#ifdef SWIGWORDSIZE64
%define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE)
%clear NEW_TYPE;
%apply TYPE { NEW_TYPE };
%enddef // PRIMITIVE_TYPEMAP
PRIMITIVE_TYPEMAP(long int, long long);
PRIMITIVE_TYPEMAP(unsigned long int, long long);
#undef PRIMITIVE_TYPEMAP
#endif // SWIGWORDSIZE64
上下文
我有一个带有重载 int
和 int64_t
的 C++ 代码,我需要将其包装到 Java
#include <cstdint>
int foo(int param);
int foo(int64_t param);
};
还有这一口
%{
#include <cstdint>
%}
%include "stdint.i"
%include "typemaps.i"
%ignore "";
%rename ("foo") foo(int);
%rename ("foo") foo(int64_t);
%include "foo.hpp";
海湾合作委员会
使用 GCC 时 int64_t 将被定义为 long int
grepc -rn "typedef.*INT64_TYPE" /lib/gcc
/lib/gcc/x86_64-linux-gnu/9/include/stdint-gcc.h:43:typedef __INT64_TYPE__ int64_t;
然后
gcc -dM -E -x c++ /dev/null | grep __INT64
#define __INT64_TYPE__ long int
所以我使用 -DSWIGWORDSIZE64
来避免 wrapper 类型错误的问题
grep "int64" -C 1 /usr/local/share/swig/4.0.1/stdint.i
#if defined(SWIGWORDSIZE64)
typedef long int int64_t;
#else
typedef long long int int64_t;
#endif
到目前为止还不错(至少在 python 和 csharp 中),但是在 Java...
痛饮Java
in Java SWIG swig 似乎将 C++ long int
包装到 C Wrapper int
(也将 2^64 截断为 2^32...)
参考:http://www.swig.org/Doc4.0/SWIGDocumentation.html#Java_default_primitive_type_mappings
来源:https://github.com/swig/swig/blob/master/Lib/java/typemaps.i
所以这两种方法将具有相同的原型 -> 我当前的问题
AFAIK java/typemaps.i nor java.swg 支持 SWIGWORDSIZE64
开关...
测试协议
重现问题(我使用的是 swig 4.0.1)
mkdir -p gen
swig -DSWIGWORDSIZE64 -I. -c++ -java -o gen/foo_java_wrap.cc -package com.google.Foo -module main -outdir gen foo.i
观察到
foo.hpp:9: Warning 516: Overloaded method baz(int64_t) ignored,
foo.hpp:8: Warning 516: using baz(int) instead.
cat gen/main.java
...
package com.google.Foo;
public class main {
public static int baz(int param) {
return mainJNI.baz__SWIG_0(param);
}
}
预计
cat gen/main.java
...
package com.google.Foo;
public class main {
public static int baz(int param) {
return mainJNI.baz__SWIG_0(param);
}
public static int baz(long param) {
return mainJNI.baz__SWIG_1(param);
}
}
那么我该如何处理这个问题呢?
谢谢
编辑:你可以在这里找到这个例子:https://github.com/Mizux/swig_java (ed可以点徽章看logs/files)
一个丑陋的解决方法是不使用SWIGWORDSIZE64
,因此int64_t
将被定义为long long
将被映射为 jlong
。
参见:http://www.swig.org/Doc4.0/SWIGDocumentation.html#Java_default_primitive_type_mappings
BUT,在 C++ 扭曲文件中,您将有一些 long long
需要修补(例如使用 post 进程 sed -i -e 's/long long/int64_t/g'
) 否则编译失败,因为 long long
与 int64_t
(又名 long int
)
您可以尝试提供自己的类型映射。
%include "stdint.i;"
#ifdef SWIGWORDSIZE64
%define PRIMITIVE_TYPEMAP(TYPE, JNITYPE, JTYPE)
%clear TYPE;
%typemap(jstype) TYPE "JTYPE";
%typemap(javain) TYPE "$javainput";
%typemap(jtype) TYPE "JTYPE";
%typemap(jni) TYPE "JNITYPE";
%typemap(in) TYPE %{ = (_ltype)&$input; %}
%typemap(freearg) TYPE "";
%typemap(out) TYPE %{ $result = ; %}
%typemap(javaout) TYPE %{ return $jnicall; %}
%enddef // PRIMITIVE_TYPEMAP
PRIMITIVE_TYPEMAP(long int, jlong, long);
PRIMITIVE_TYPEMAP(unsigned long int, jlong, long);
#undef PRIMITIVE_TYPEMAP
#endif // SWIGWORDSIZE64
因为您想重用 long long
类型映射:
#ifdef SWIGWORDSIZE64
%define PRIMITIVE_TYPEMAP(NEW_TYPE, TYPE)
%clear NEW_TYPE;
%apply TYPE { NEW_TYPE };
%enddef // PRIMITIVE_TYPEMAP
PRIMITIVE_TYPEMAP(long int, long long);
PRIMITIVE_TYPEMAP(unsigned long int, long long);
#undef PRIMITIVE_TYPEMAP
#endif // SWIGWORDSIZE64