2014-01-14 2 views
0

У меня странная проблема при использовании функции MLApp.GetWorkspaceData. Я заметил, что эта функция работает должным образом, если я делаю следующее:"Invalid Calle" при использовании MLapp в C#

matlab = new MLApp.MLAppClass(); 

object myObject; 

matlab.GetWorkspaceData("myVariable", "base", out myObject); 

Но если я тогда попробуйте использовать один и тот же объект, как выход, я получаю «Invalid» исключение вызванного метода. Кроме того, это также дает ту же ошибку:

matlab = new MLApp.MLAppClass(); 

object myObject = new object(); 

matlab.GetWorkspaceData("myVariable", "base", out myObject); 

Это очень хлопотно, потому что мне нужно, чтобы получить большое количество данных из Matlab в Visual Studio, и я не могу практически создать 52K неинициализированные переменные и держать их вокруг. Есть ли способ «uninitialize» переменной? Есть ли какая-то концепция, которую я здесь отсутствует?

+1

Вы можете установить 'myObject = null;', и сборщик мусора должен сделать остальное в какой-то момент. – wonko79

+0

Wonko, этот актуал, похоже, сработал. Но я до сих пор не знаю, что происходит. Почему я не могу присвоить «новую» переменную? Почему он должен быть неинициализирован? – Cashomoto

+0

Поскольку вы вызываете Mathlab поверх COM-оболочки, возможно, это связано с тем, что процесс не может изменить материал другого или что-то в этом роде. – wonko79

ответ

1

В качестве комментариев @wonko79, если вы хотите повторно использовать переменную out, вы должны сначала установить ее на null.

Вот проверенный пример calling MATLAB from C#:

using System; 

namespace CSharp_matlab_com 
{ 
class Program 
{ 
    static void Main(string[] args) 
    { 
     MLApp.MLAppClass matlab = new MLApp.MLAppClass(); 

     // create variables: a_0, a_1, ..., a_4 
     for (int k = 0; k < 5; k++) { 
      matlab.Execute(string.Format("a_{0} = rand(2);", k)); 
     } 

     // retrieve variables from MATLAB and print their contents 
     object a; 
     for (int k = 0; k < 5; k++) { 
      // current variable name 
      string varname = string.Format("a_{0}", k); 

      // get data array 
      a = null; // without this line, an exception is thrown! 
      matlab.GetWorkspaceData(varname, "base", out a); 

      // print contents 
      var arr = (double[,]) a; 
      Console.WriteLine("\nndims(a) = {0}, numel(a) = {1}", arr.Rank, arr.Length); 
      for (int i = 0; i < arr.GetLength(0); i++) { 
       for (int j = 0; j < arr.GetLength(1); j++) { 
        Console.WriteLine("{0}[{1},{2}] = {3}", varname, i, j, arr[i,j]); 
       } 
      } 
     } 
    } 
} 
} 

Выход:

ndims(a) = 2, numel(a) = 4 
a_0[0,0] = 0.251806122472313 
a_0[0,1] = 0.617090884393223 
a_0[1,0] = 0.290440664276979 
a_0[1,1] = 0.265280909810029 

... 

ndims(a) = 2, numel(a) = 4 
a_4[0,0] = 0.425259320214135 
a_4[0,1] = 0.16148474431175 
a_4[1,0] = 0.312718886820616 
a_4[1,1] = 0.178766186752368 
0

Вы можете создать оболочку для GetWorkspaceData метода, как в следующем примере:

public object GetData(string name) 
{ 
    object data; 
    mlApp.GetWorkspaceData(name, "base", out data); 

    return data; 
} 

Или, что еще более полезно, общая обертка:

public T GetData<T>(string name) 
{ 
    object data; 
    mlApp.GetWorkspaceData(name, "base", out data); 

    if (data == null) 
     return default(T); 

    if (data is T) 
     return (T)data; 
    else 
     throw new InvalidCastException($"The variable '{name}', of type '{data.GetType().Name}' cannot be casted to type '{typeof(T).Name}'."); 
}