Могу ли я сделать так, чтобы параметры других языков работали в Scala? - PullRequest
1 голос
/ 21 ноября 2011

Я подключаю scala к некоторому нативному коду (через java + jna) и собираюсь переписать API, используя кортежи и несколько возвращаемых параметров. Но мне интересно, есть ли лучший способ (с последствиями или что-то).

Например, у меня может быть подпись метода типа

MyLib.__stdcall aMethod(String inParam, String[] out1, int[] out2);

Где находятся массивы, чтобы я мог получить значения в Java:

String[] out1 = new String[1];
Int[] out2 = new Int[1];

lib.aMethod("in", out1, out2);

String theRealOut1Value = out1[0];
Int theRealOut2Value = out2[0];

и вуаля! Как просто!

Я почти уверен, что единственное разумное, что нужно сделать, - это создать обертку с (scala) методом, например:

aMethodWrapper(in : String) : (String, Int)

Я не надеюсь, но я вижу магию на каждом шагу в скале, поэтому мне было интересно:)

Ответы [ 3 ]

3 голосов
/ 21 ноября 2011

Вы можете создать следующую вспомогательную функцию:

def call[A](f: Array[A] => Unit)(implicit m: Manifest[A]): A = {
  val outA = new Array[A](1)
  f(outA)
  outA(0)
}

... и для двух аргументов:

def call[A, B](f: (Array[A], Array[B]) => Unit)
             (implicit m1: Manifest[A], m2: Manifest[B]): (A,  B) = {
  val outA = new Array[A](1)
  val outB = new Array[B](1)
  f(outA, outB)
  (outA(0), outB(0))
}

После этого вы можете вызывать библиотечные функции следующим образом:

call[String](lib.aMethod("foo", _))

и

call[String, Int](lib.bMethod("bar", 1, _, _))
2 голосов
/ 21 ноября 2011
def aMethodWrapper(in : String) : (String, Int) = {
    val out1 = new Array[String](1);
    val out2 = new Array[Int](1);

    lib.aMethod(in, out1, out2);
    (out1(0), out2(0));
}
2 голосов
/ 21 ноября 2011

Я думаю, я понял это. Объявите ссылочный тип и неявные преобразования:

class Ref[T : Manifest] {
  val reference = new Array[T](1);  
}

implicit def ref2Array[T : Manifest](ref :Ref[T]) : Array[T] = ref.reference;
implicit def ref2Object[T: Manifest](ref : Ref[T]) : T = ref.reference(0);

Это позволяет мне написать приведенный выше код следующим образом

def aMethodWrapper(in : String) : (String, Int) = {
    val out1 = new Ref[String];
    val out2 = new Ref[Int];

    lib.aMethod(in, out1, out2);
    (out1, out2);
}

Я думаю, что это читает целую кучу лучше, чем раньше, и указывает, для каких параметров.

Если кто-то может предложить улучшенный результат, я поставлю вам галочку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...