PDA

View Full Version : dotNet help needed! How to call this method?


martinB
10-23-2009, 04:50 PM
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

biddle
10-23-2009, 05:17 PM
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 "[%,%] = %\n" 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

martinB
10-23-2009, 05:47 PM
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

martinB
10-26-2009, 01:25 PM
*bump*

Does anyone else have suggestion what I could try to call that assembly without errors?

Thanks!
-- MartinB

LoneRobot
10-26-2009, 02:32 PM
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?

martinB
10-26-2009, 02:51 PM
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

LoneRobot
10-26-2009, 05:35 PM
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.

biddle
10-26-2009, 05:44 PM
...I hadn't forgotten this. Sorry to hear you are still having problems.

I will see what the debugger says about the wonky parameters.

biddle
10-26-2009, 08:14 PM
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]

LoneRobot
10-26-2009, 10:04 PM
woof! now that is a solution. Great stuff, Mike.

martinB
10-27-2009, 02:29 PM
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.

[...]

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]

Awesome man! I am speechless to see someone go to that length of actually debugging the 3ds Max SDK to fix my problem! I'll digest that for a bit and will definitely get back to you. FWIW, I am on 3ds Max 2010 64bit.

Respect!
-- MartinB

martinB
10-27-2009, 03:40 PM
OK, Mike, you're now the official hero of the day!!

After removing a stupid mistake in my script this works just beautifully. And it is a great showcase that demonstrates how priceless it is to have access to the source code of your software.

I'll try to talk to Autodesk about officially fixing that. Maybe they can include this in a hotfix?

Mike, would you please PM me with your email address?

THANKS!
-- MartinB

biddle
10-27-2009, 04:12 PM
You are certainly welcome, but I will come clean and say that there was a wee bit of self-interest motivating me :)

I've been calling LAPACK/BLAST libraries from the SDK to solve minimization problems in an LOD modifier I've been working on. I really wanted to figure out how to leverage AlgLib from mxs as the .NET interface is cleaner. Fixing your problem and proving it would work (if mxs behaved better) has given me all sorts of ideas on how I can tidy up my stuff.

Please do submit that bug for me, I'd appreciate it.

.biddle

CGTalk Moderation
10-27-2009, 04:12 PM
This thread has been automatically closed as it remained inactive for 12 months. If you wish to continue the discussion, please create a new thread in the appropriate forum.