SWIG Java конвертировать int64_t в jlong ​​при использовании -DSWIGWORDSIZE64 - PullRequest
0 голосов
/ 13 февраля 2020

Context

У меня есть код C ++ с перегрузкой int и int64_t, который мне нужно обернуть в Java

#include <cstdint>

int foo(int param);
int foo(int64_t param);
};

и этот swig

%{
#include <cstdint>
%}

%include "stdint.i"
%include "typemaps.i"

%ignore "";
%rename ("foo") foo(int);
%rename ("foo") foo(int64_t);

%include "foo.hpp";

G CC

При использовании G CC 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 чтобы избежать проблем с неправильным типом оболочки

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 ...

SWIG Java

в Java SWIG Swig, кажется, оборачивает C ++ long int в C Wrapper int (также обрезая 2 ^ 64 до 2 ^ 32 ...) Ref: http://www.swig.org/Doc4.0/SWIGDocumentation.html#Java_default_primitive_type_mappings Sr c: 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 вы можете нажать на значок, чтобы увидеть журналы / файлы)

Ответы [ 3 ]

0 голосов
/ 13 февраля 2020

Вместо этого вы можете попытаться предоставить собственную карту типов.


%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 %{ $1 = ($1_ltype)&$input; %}
%typemap(freearg) TYPE "";
%typemap(out) TYPE %{ $result = $1; %}
%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
0 голосов
/ 13 февраля 2020

Поскольку вы хотите повторно использовать карту типа 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
0 голосов
/ 13 февраля 2020

Обходной некрасивый обходится до , а не , используйте SWIGWORDSIZE64, поэтому int64_t будет typedef до long long, который будет преобразован в jlong. см .: http://www.swig.org/Doc4.0/SWIGDocumentation.html#Java_default_primitive_type_mappings

НО , в файле деформации C ++ у вас будет long long, который вам нужно исправить (например, с помощью постобработки sed -i -e 's/long long/int64_t/g') в противном случае компиляция завершится неудачно, поскольку long long отличается от типа int64_t (он же long int)

...