Register to post in forums, or Log in to your existing account
 

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD Beta Forum
Anaristos
Sorcerer


Joined: 17 Jul 2007
Posts: 821
Location: California

PostPosted: Tue Dec 29, 2009 9:07 am   

[2.xx,3.xx] COM problem (A solution found)
 
Zugg, I know you were not interested in fixing the COM problems, but I will continue to post them anyway since they affect me and will affect anyone else that attempt to use this feature. The number of users wanting to use COM objects will increase when non-mudders start using CMUD as a front-end anyway. So here it goes...

If an external application has the following signature
Code:

public rettype methodname(vartype param1, object[] param2) {....} // C, C++, C#

or
Code:

public rettype methodname(vartype param1, params object[] param2) {....} // C# only

or
Code:

public rettype methodname(params object[] param1) {....} // C# only


you will pass the parameters to the application incorrectly and either INVALID NUMBER OF PARAMETERS or THE PARAMETER IS INVALID is returned as a parsing error.

If I call a method using one of these types of signatures from a C, C++, or C# application there is no problem, so the problem must lie with CMUD.

IMO what is happening is that CMUD is looking at the method signature and trying to marshal the parameters it sees in the COM function call to the application to match the signature (which is fine), but since an array is being used (or not, as it is sometimes the case with C#) and a mixed parameter list is involved, it passes the paremeters incorrectly.
For instance, in the 3rd case above, one can pass a regular CSV list to the application and the CLR will marshal it into an array for consumption by the method (params is a keyword that indicates a variable number of parameters), but CMUD seeing an array signature, will complain.
Perhaps this comes about because at the time COM for ZMUD was developed, the 2nd and 3rd type of signatures didn't exist and, therefore, are not being taken into account (this doesn't explain with the first type of signature fails, though).
Without this fix, one is forced to write a method overload for each parameter count, rather than passing a variable parameter list to the method.
One way to get around these problems, I think, is to ignore the target signature and pass the parameters as a CSV and let the target application front-end worry about whether the parameter list is correct or not.
Oddly enough, when a Python script is invoked from CMUD (via COM) using a CSV list, it works just fine even though the method signature looks like this:
Code:

def MethodName (var1, *var2)

which , as you can see, is equivalent to the 2nd signature above.
_________________
Sic itur ad astra.

Last edited by Anaristos on Tue Jan 05, 2010 12:06 am; edited 1 time in total
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Mon Jan 04, 2010 6:32 pm   
 
When ever you have any sort of COM array argument, you will need to use the %array function in CMUD to create the proper parameter list.

Also, keep in mind that C# is creating a .NET interface and not a traditional COM interface. The COM support in CMUD (and zMUD) is the traditional COM API and doesn't have any extensions for anything Microsoft added to COM with .NET.

At the low level you are describing, there is very little I can do. I'm calling the COM routines supplied by Delphi to execute a COM object method or retrieve a COM property. I don't do any of the low-level marshaling myself.

This kind of stuff has always been an issue for COM. It really isn't as "language independant" as it should be. Obviously if your COM object is created in C/C++/C# and then called from a C/C++/C# application it is going to work fine because both are using the same exact types of data structures. But calling your C/C++/C# COM object from another language (like Delphi) has a completely different implementation of arrays.

The fact that CMUD is working with your last Python example tends to make me think that Python is handling it correctly but that your C/C++/C# system is using some sort of Microsoft extension that isn't part of the basic COM API or something.
Reply with quote
Anaristos
Sorcerer


Joined: 17 Jul 2007
Posts: 821
Location: California

PostPosted: Tue Jan 05, 2010 12:05 am   
 
I have found a solution to the problem. Taking into account that you are using Delphi as the COM driver I am now passing the paramters to the mthod this way:
Code:

$rec = @comobj.MethodName("param1",%array("param2",....,"paramN"))

which seems to be working.
Delphi IS misreading the target method signature, however.
If the target method signature is
Code:

public rettype methodname(string str, params object[] param2)

it should just pass the parameters as is rather than expect an array as the second parameter. The params keyword indicates to the runtime that if parameters from that position on are simple ones, they will be handed to the method in an array, it doesn't mean that an array is expected (though not excluded, in which case the runtime expects a single array parameter).
So by including the params keyword in the array the method can be called also this way
Code:

$rec = MethodName("param1", "param2",....,"paramN")

In this case the runtime stuffs "param2" through "paramN" into an array and hands it to the method. So both call styles are equivalent.

At any rate I am glad that there is a solution. Thanks for your patience.

EDIT note to those writing applications, the array must be of object[] type, if any other type is used, CMUD will get a type mismatch error.
_________________
Sic itur ad astra.
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Tue Jan 05, 2010 5:26 pm   
 
Actually, CMUD or Delphi is "misreading" anything. Nothing in the COM system that CMUD is using actually reads the signatures. CMUD is not looking at the Type Library for your object (because some COM objects don't have type libraries). CMUD and Delphi are just passing the arguments without looking at them. That's why I said you needed to use %array to create a proper COM array to send to your object.

I haven't looked at this stuff in a long time and don't really know anything about the "params" keyword. Is it possible that this is something that was added later to the COM spec by Microsoft in .NET and isn't supported by the older COM API? In other words, is this just something used in C/C++/C#, or is it really part of the COM spec somewhere? Because it seems like that kind of stuff should be happening in the lower level part of Windows. If CMUD just passes regular arguments, shouldn't the low-level COM system be detecting the "params" keyword and then handling the arguments properly? CMUD isn't working at that kind of low level.
Reply with quote
Zugg
MASTER


Joined: 25 Sep 2000
Posts: 23379
Location: Colorado, USA

PostPosted: Tue Jan 05, 2010 5:27 pm   
 
Oh, also, if you have a DLL that uses the "params" keyword, go ahead and send it to me along with instructions on how to call it. I can play around with some Delphi test programs to see if it's really something I can handle on my end or not. It's also possible that the newer version of Delphi has improved some of this.
Reply with quote
Anaristos
Sorcerer


Joined: 17 Jul 2007
Posts: 821
Location: California

PostPosted: Tue Jan 05, 2010 11:55 pm   
 
OK, I will build a small test case and mail it to you.

The one drawback with the solution I am using, which really is indicative of the overall problem, is that I have to send an array with a null element (because CMUD won't create empty arrays), when one doesn't want to pass any parameters.

So if the signature is
Code:

public rettype methodname(params object[] args)

and I don't want to pass any paramenters (params is used when the arguments beyond the keyword are optional) then I have to do this from CMUD
Code:

#CALL @comobj.methodname(%array(%null))

if done this way, it will get an "invalid number of parameters" error.
Code:

#CALL @comobj.methodname()


NOTE: The reason Python has no problems with using either signature (from the original post) is because it is not a strongly typed language. It is up to the method to check how the parameters were passed. So if you pass 4 string arguments or 1 string argument and and array with 3 strings in it, it won't complain. Unfortunately, Windows 7 is having problems with Python Windows scripts at the moment so I can't test this aspect any further.
_________________
Sic itur ad astra.
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD Beta Forum All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum

© 2009 Zugg Software. Hosted by Wolfpaw.net