I was trying to pass a 3D array into a MATLAB function from C# with COM. Here's my code:
// here's the code in C#
MLApp.MLApp matlab = new MLApp.MLApp();
//load function
matlab.Execute(#"cd C:\Users\1303092.local\Matlab\EmGm");
//initialized input and output
int[,,] data1 = new int[2,3,5]{{{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5}},{{1,2,3,4,5},{1,2,3,4,5},{1,2,3,4,5}}};
object result1 = null;
object result2 = null;
//use function with the data from C#
matlab.Feval("myfunc", 2, out result1, data1);
//type casting
object[] res1 = result1 as object[];
double[, ,] data2 = res1[1] as double[, ,];
//use function with the casted data from MATLAB
matlab.Feval("myfunc", 2, out result2, data2);
object[] res2 = result2 as object[];
// here's the MATLAB function
function [x,y] = myfunc(a)
x = a;
y = ones(2,3,5);
end
I have inserted a breakpoint at the end of the code to check the value in the variables, which is shown as:
click here for image
It seems C# has no difficulty with taking the return values since it did recognise the returned parameter "y". However, there may be some type casting issue when MATLAB takes the array from C#, since the returned parameter "x" was always been recognised as NULL in C#.
I have also tried 2D array in the exactly same way, and everything was running well. Is the error related to the dimensionality here? Any idea guys?
Related
I am trying to pass a cell array (tried a table as well) from Matlab to my C# application. How do I do this?
I can pass a string to my c# application from Matlab but can't seem to pass a vector of strings or a cell array (which contains dates & text)
Matlab Code
DllPath = 'C:\MyPath\MyLibrary.dll';
ass = NET.addAssembly(DllPath);
myCls = AssName.ClassName;
colName = [{'abc'}; {'des'}];
myCls.Foo('sddsdd', colName);
The function below is not useful at the moment I'm just using it to play around with. I can read the tableName variable fine & I can cast the colName variable to a string[].
C#
public int Foo(string tableName, object colName)
{
string[] arr = ((IEnumerable)colName).Cast<object>()
.Select(x => x.ToString())
.ToArray();
Console.WriteLine(tableName);
Console.WriteLine(arr.Length);
return arr.Length;
}
My C# COM DLL has a method that accepts a float array and a long int array. It returns a float.
From VBA in an MS Access module, I create an array of type single and another of type long, populate them, create the DLL app.class object and then call its method with the two arrays. But I get a "type mismatch" error.
The following is the actual code, but it is simple because I'm trying to work out the communications before adding the "real" code.
C# code:
public float JustTesting(float[] Array1, long[] Array2)
{
return 96.0F;
}
VBA code:
Public Sub Test()
Dim a1(0 To 0) As Single, a2(0 To 0) As Long, sng As Single
a1(0) = 5
a2(0) = 10
Dim o As Variant
Set o = CreateObject("MyApp.MyClass")
sng = o.JustTesting(a1, a2)
Debug.Print CStr(sng)
Set o = Nothing
End Sub
Where is the data type mismatch?
A Long in VBA is only 32 bits, the same was as an int in C#. So your method needs to take an array of ints
public float JustTesting(float[] Array1, int[] Array2)
{
return 96.0F;
}
I'm trying to make some test data with which to test some functionality of my code. To this end, I need a double[][]. I am trying to do with a function that takes a double[][] as an input parameter and copying onto it a local variable containing the test data. However, I get an error that I don't quite understand (I'm sure it's a very basic error, which is why I'm unable to Google it), understanding/fixing which I'd appreciate any help.
private void makeData(double[][] patterns)
{
double[][] data = new double[2][];
// exists so that I can change `data` easily, without having to change the core functionality of copying it over to `patterns`
data[0] = {1.0,8.0}; // error!
// copy over everything from data into patterns
}
The line marked in the above code is giving me the error Only assignment, call, increment, decrement, and new objects can be used as a statement. To this, my reaction is "Isn't data[0] = {1.0,8.0}; an assignment?
I'm fairly confused, so I'd appreciate any help
You want to do
data[0] = new[] {1.0, 8.0};
The curly brace initializers are only valid if you're creating an object/array. They don't work by themselves.
You can specify the type specifically:
data[0] = new double[] {1.0, 8.0};
But you don't have to if the compiler can infer the right type (which, in your case, it can).
Just replace:
data[0] = {1.0,8.0};
by:
data[0] = new double[] { 1.0, 8.0 };
The compiler has to know explicitly what to assign to data[0]. It doesn't infer it from the type of data[0].
You should to initialize your subarray first.
double[][] data = new double[2][];
data[0] = new double[] {1.0f, 8.0f};
So I have this object in C#, which will contain ints and bools (doubles and logicals)
object[,] matrixData = new object[iDimensions[0], iDimensions[1]];
and I pass it to matlab:
matlab.PutWorkspaceData("matrixData", "base", matrixData);
Matlab sees this as a cell array of arrays. Which is inconvenient since I now cannot use these values for anything. I guess I need to convert these into a numerical array - although in truth I'd be happier to retain the strong typing and just lose the array within each cell.
So, for example:
temp = cell(1,4)
temp{1,1} = [0.5]
temp{1,2} = [1==1]
temp{1,3} = [7424.356]
temp{1,4} = [31]
and I want to have:
output = [0.5, 1==1, 7424.356, 31]
So my current implementation is pretty crass:
cellfun(#decellify,CashFlowBasisMatrixData);
where
function decellified = decellify(object)
if isa(object,'logical')
decellified = +object;
end
if isa(object,'float')
decellified = object;
end
if isa(object,'char')
decellified = -2;
end
end
Is there a better way? If I do the conversion to doubles in C# how do I 'un-array' each element?
Thanks,
Nt
A COM component exposes an API which expects a ref param of object type. As per the documentation of this API, it will fill the ref object with array of values. Now my problem is in prod env I can't predict the number of elements which I will get back.
Following code will work.
COMClass objCOM = new COMClass ();
object colOfInts= new int[10]; // What if I don't know the following will return array of size 10?
int errorcode = objCOM.FillThisIn(ref colOfInts);
But what if I don't know the size of array that API returns in ref.
Update here
object colOfInts = null;
int errorcode = objCOM .FillThisIn(ref colOfInts);
now when I check the type I get System.Int32[*]
Basically I need to iterate through this array and check for the presence of an element
You are getting back an array whose lower bound isn't 0. That's not uncommon in COM interop, the next likely choice is 1. You don't have to copy it, you can access the elements with Array.GetValue(). Array.GetLowerBound() tells you where to start, Array.GetLength() or Array.GetUpperBound() tells you how far to go.
Finally I got some solution on this . Forgot to mention erroCode will have the size of the array.
int[] test = new int[errorCode];
Buffer.BlockCopy((System.Array)colOfInts, 0, test, 0, errorCode * sizeof(int));
If you're getting back an array of System.Int32, you probably just need to cast:
object colOfInts = null;
int errorcode = objCOM .FillThisIn(ref colOfInts);
int[] arrayOfInts = (int[]) colOfInts;
Then arrayOfInts.Length will have the number of elements in the array.