[Closed] dotNet help needed! How to call this method?
So I have this 3rd party .Net assembly. When I load it into 3ds Max and create an object from one of the assembly classes, I can run ‘showMethods’ on it and get this:
.[static]<System.Boolean>rmatrixsvd <System.Double[,]>a <System.Int32>m <System.Int32>n <System.Int32>uneeded <System.Int32>vtneeded <System.Int32>additionalmemory <System.Double[]&>w <System.Double[,]&>u <System.Double[,]&>vt
So, how do I call that method? How do I create the appropriate MAXScript values or dotNet values so they match that defintion?
Whatever I have tried so far (including converting the MXS values to dotNet values using dotNet.ValueToDotNetObject()) gave me
-- Runtime error: No method found which matched argument list
I assume the problem are the last three parameters, which are 1D and 2D double arrays passed by value if I understand it correctly.
I am a dotNet beginner, so any help would be much appreciated!
Thanks very much in advance
– MartinB
Without the library, I can’t be sure. Looks like it calls into LAPACK.
Here are some ideas you can test
– Declare the dimensions (is it MxN or NxM)
m = 3
n = 2
– Declare the arrays
a = dotnetobject “System.Double[,]” m n
w = dotnetobject “System.Double[]” n
u = dotnetobject “System.Double[,]” m n
vt = dotnetobject “System.Double[,]” m n
– Check the type
dotnet.gettype a
– Fill in the input array
for i = 0 to (m-1) do
for j = 0 to (n-1) do
a.set i j (i*n+j)
– Dump it to be sure
for i = 0 to (m-1) do
for j = 0 to (n-1) do
format “[%,%] = %
” i j (a.get i j)
– When you make the call, the last three args are passed by reference
success = rmatrixsvd a m n uneeded vtneeded additionalmemory &w &u &vt
Awesome, thanks very much! I still get that error, but I feel a lot closer to the solution.
It never occurred to me to construct the double arrays the way you showed, I always tried to directly convert a MAXScript array. That isn’t possible, is it?
Anyway, I still get ‘No method found which matched argument list’. Too bad the system doesn’t tell me which parameter doesn’t match… :\
The method definition in the (C#) source code is as follows:
public static bool rmatrixsvd(double[,] a,
int m,
int n,
int uneeded,
int vtneeded,
int additionalmemory,
ref double[] w,
ref double[,] u,
ref double[,] vt)
FWIW, I have the library attached, hope this helps finding the right parameters?
Thanks again!
– MartinB
bump
Does anyone else have suggestion what I could try to call that assembly without errors?
Thanks!
– MartinB
hi martin,
i took a quick look in visual studio to see if intellisense would yield any clues but it doesnt seem to have any extra info. Can you say any more about what the assembly does or the range of values it is expecting?
Pete,
thanks very much for your interest.
The assembly is part of a math library to do matrix operations (this one performs a singular value decomposition, in particular).
The C# source code for that method starts with:
public static bool rmatrixsvd(double[,] a,
int m,
int n,
int uneeded,
int vtneeded,
int additionalmemory,
ref double[] w,
ref double[,] u,
ref double[,] vt)
{
Not knowing C# or dotNet, I assume that it wants a two-dimensional double array a, some integers, and some more arrays with have to be passed by-reference.
Just to keep things simple and break it down in small parts, I wrote this tiny method to test how I could pass arguments from MAXScript:
public static bool mbtest(double[,] a)
{
bool result = new bool();
return result;
}
Then I build this into the assembly, load it into 3ds Max, create a new object and try to call that method:
a = dotNetObject "System.Double[,]" 2 2
a.gettype()
-- dotNetObject:System.RuntimeType[System.Double[,]]
o.mbtest a
-- Runtime error: No method found which matched argument list
o.mbtest #(1.0d0,1.0d0,1.0d0)
-- Runtime error: dotNet runtime exception: Object of type 'System.Double[]' cannot be converted to type 'System.Double[,]'.
o.mbtest #(#(1.0d0,1.0d0),#(1.0d0,1.0d0))
-- Runtime error: No method found which matched argument list
so I am stuck even at this simple level. :-\
Any ideas?
– MartinB
thanks for that Martin,
Ill try to look into it and see. I dont know C# so perhaps somebody could clarify but the ‘ref’ part, i think is just how you pass variables to functions in dotnet – you can do it by a duplicate variable (byVal in VB) or by reference to the actual data itself, (Byref in VB)
I will try to work out the correct syntax.
…I hadn’t forgotten this. Sorry to hear you are still having problems.
I will see what the debugger says about the wonky parameters.
There is a bug in Maxscript.
In mxsdotnet/utils.cpp there are two places where multidimensional arrays are incorrectly re-typed as 1D vectors. The type of the 1D vector of Doubles is then checked to see if it can be assigned from a 2D array of Doubles. It can can't be, the args don't match, and you can't call your method.
There are really only two ways I can see around this:
1. Add a helper function to your library that allows you to pass in all the 2D array arguments from maxscript as 1D vectors (that are m*n in length). This helper would have to convert from 1D to 2D before making the call, and then back to 1D afterwords.
2. Fix the bug in maxscript. You will need the SDK installed to do this.
I picked option 2, because there is nothing wrong with that library :)
There are TWO places in utils.cpp that are broken: The MXS_Value_To_Object method and the CalcParamScore method.
In both places, change the code that looks like this:
// for 'byref' and 'byptr' types, get the underlying type. But don't lose whether we are
// dealing with an Array type.
System::Type^ l_pOrigType = type;
if (type->HasElementType)
{
type = type->GetElementType();
if (l_pOrigType->IsArray)
{
type = type->MakeArrayType();
}
}
To this:
// for 'byref' and 'byptr' types, get the underlying type. But don't lose whether we are
// dealing with an Array type.
System::Type^ l_pOrigType = type;
if (type->HasElementType)
{
type = type->GetElementType();
if (l_pOrigType->IsArray)
{
if (l_pOrigType->GetArrayRank() == 1)
{
// This is a 1D vector
type = type->MakeArrayType();
}
else
{
// This is a multidimensional array
type = type->MakeArrayType(l_pOrigType->GetArrayRank());
}
}
}
Once this fix is in, the code snippet that I sent you earlier works correctly.
success = svd.rmatrixsvd a m n uneeded vtneeded additionalmemory &w &u &vt
[I've attached a recompiled version of mxsdotnet.dlx for 3dsmax 2010 that has this fix applied if you want to try it. PM me if you need a different version]