Может ли MATLAB не читать массив double [] из Java? - PullRequest
6 голосов
/ 05 апреля 2011

Рассмотрим MyClass.java:

public class MyClass {
  public void firstfunction(double fwd[]) {
   fwd[0] = 42;
  }
  public void secondfunction(Double fwd[]) {
   fwd[0] = new Double(42);
  }
}

Обе функции возвращают значение 42 в fwd, верно?

Из MATLAB я хочу получить доступ к этому значению 42:

myobj=MyClass;
var1=0.0;
myobj.firstfunction(var1);
fprintf('%1.1f',var1);         %// ... var1 is still 0.0 ...       :-(

var2 = javaArray ('java.lang.Double',1);
var2(1)=java.lang.Double(0.0);
myobj.secondfunction(var2);    %// var2 now contains the value 42  :-)

Пока оба вызова «работают» (как: без сообщения об ошибке), только var2 содержит возвращаемое значение 42;var1 по-прежнему имеет значение 0.0.

Можно ли использовать MATLAB для вызова функции firstfunction и получения возвращаемого значения?


Некоторый фон: MATLAB может передавать объекты Java при вызове функции Java, и впоследствии эти модификации доступны в MATLAB - , за исключением , когда объект Java является массивом примитивного типа данных.В этом случае происходит автоматическое преобразование между MATLAB и Java, в результате чего массив Java-массива-примитива-двойника напрямую соответствует двойной матрице в MATLAB - что в соответствии с соглашениями MATLAB вещь «передается как значение», поэтому возвращаемые значения невозможны.Так что мой вопрос можно перефразировать как , есть ли способ обойти это?


(вы можете перестать читать здесь.)

Для справки, мой особый случай был таким:

У меня есть класс Java MyClass.java, обертывающий DLL, которую я хочу использовать в MATLAB.Однако возвращаемое значение одной из функций - это double [], передаваемый в качестве параметра , содержимое которого не возвращает его обратно в MATLAB из-за того, как взаимодействует с Java

Есть ли способ обойти эту проблему, не изменяя способ, которым DLL возвращает данные?

Вот ужасные детали:

public class MyClass
{
    static
    {
        System.load("C:\\fullpath\\mydll.dll");
    }
public static native long   SetFWD(double fwd);
public static native long   GetFWD(double fwd[]);
}

Этовидимый из MATLAB, как только я правильно установил javapath:

>> methods MyClass -full

Methods for class MyClass:

static long GetFWD(double[])
MyClass()
static long SetFWD(double)
[and stuff inherited from java.lang.Object]

Я могу вызвать функцию SetFWD из MATLAB, но я не могу заставить GetFWD что-либо вернуть:

myobj=MyClass;
fwd=3.0;
myobj.SetFWD(fwdval); % this works fine
fwd=0.0;
myobj.GetFWD(fwd); % this does not give an error, but fwd stays unmodified - as one would expect in MATLAB
fwd = javaArray ('java.lang.Double',1);
fwd(1) = java.lang.Double(0.0);
myobj.GetFWD(fwd) % this gives the error "??? No method 'GetFWD' with matching signature found for class 'MyClass'."

Из чтения документации MATLAB Передача данных в метод Java и Работа с массивами Java , а также сообщения SO Переход от типов Java обратно к типам MATLAB и Странные классы, переданные из matlab в java , я понимаю, что Matlab автоматически преобразует любой двойной массив, который я передаю функции, в массив Java, а затем игнорирует любые изменения, вносимые в эти массивы.Кажется, что если мое определение функции в MyClass содержало объекты Double вместо двойных примитивов, моя вторая попытка могла бы сработать.

Есть ли способ получить MATLAB для возврата значения, которое я ищу, без изменения оригинала.DLL (mydll.dll)?

Обновление

Я понимаю, что MATLAB обычно передает все "по значению".Но в Передача данных в метод Java Mathworks говорит, что

Если вам нужно получить доступ к изменениям, которые метод Java вносит в массив, то вместо передачи массива MATLAB,Вы должны создать и передать массив Java, который является ссылкой.

Они объясняют в Работа с массивами Java , как это сделать с помощью функции javaArray, но я не смогзаставить это работать для создания массива double [] (т. е. массива примитивных двойников), только для Double [] (т. е. массива объектов Double), что здесь не то, что мне нужно, поскольку моя функция GetFWD () неесть последнее: - (.

>> A=javaArray ('java.lang.double',1); % works fine, but cannot be used as parameter for my function GetFWD (see "No Method ... with matching signature..." error above)
>> A=javaArray ('double',1);
??? Error using ==> javaArray
No class double can be located on the MATLAB Java classpath

Ответы [ 3 ]

3 голосов
/ 06 апреля 2011

Нет, не может.

Я нашел этот обходной путь , с которым я могу жить: хотя я не могу (сам) изменить DLL, я могу добавить функцию-обертку в java-класс MyClass вот так:

public static long  GetFWDwrp(Double fwd[]) {
    double tmp[]=new double[1];
    long retval = MyClass.GetFWD(tmp);      
    fwd[0] = tmp[0];
    return retval;
}

Эта функция-обертка имеет массив объектов Double в качестве параметра, к которому я могу получить доступ из MATLAB следующим образом:

oldFW = javaArray ('java.lang.Double',1);
oldFW(1)=java.lang.Double(0.0);
myobj.GetFWDwrp(oldFW);
oldFW % this now contains the return value

Таким образом, это отвечает на мой вопрос для обходного пути к проблеме, поскольку он не включает изменение интерфейса библиотеки DLL (только интерфейс класса Java).

Тем не менее, более фундаментальный вопрос в заголовке до сих пор остается без ответа : действительно ли невозможно в MATLAB передать ссылку на массив примитивов-удвоений в функцию Java, обходя автоматическое преобразование от Matlab-double-array до Java-primitive-double-array и обратно, что, кажется, делает невозможным доступ к любым изменениям кода Java, внесенного в такой массив.

2 голосов
/ 28 апреля 2012

Это не ошибка, ожидаемое поведение

firstfunction принимает копию примитивного двойного массива, изменяет эту копию и возвращает без изменениячто-нибудь в MyClass экземпляре.

secondfunction получает ссылку на массив java.lang.Double в качестве входных данных - поэтому MATLAB видит любые изменения, внесенные в этот массив.

В коде Java вы можете передатьссылки на двойные массивы, но они всегда будут передаваться как копии, если предоставлены как выходные или входные данные из MATLAB.

Вы можете найти оболочку, например Apache Math ArrayRealVector, но даже там, доступ к базовому массиву из MATLAB создаст копию - даже при вызове getDataRef, как Apache Mathвернет ссылку, но MATLAB скопирует ее.Однако вы можете вызвать методы ArrayRealVector setEntry и getEntry, чтобы изменить базовый двойной массив из MATLAB.

0 голосов
/ 06 апреля 2011

Попробуйте передать числовые значения в массиве ячеек Matlab, например ::100100

myobj.GetFWD({1.2, 3.4, 5.6});

или, может быть, даже обычный массив Matlab:

myobj.GetFWD([1.2, 3.4, 5.6]);

...