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

Play RetroMUD
Post new topic  Reply to topic     Home » Forums » CMUD General Discussion
Tarn
GURU


Joined: 10 Oct 2000
Posts: 867
Location: USA

PostPosted: Wed Apr 10, 2013 5:17 am   

Notes on Building a COM Component for Use by CMUD
 
A few points on building COM components for use with CMUD:

Visual Studio 2012 does not seem to be very automatic about building dual interface COM objects using C++ via ATL. It's easy to build one which is recognized when early bound by another program. Getting them to work with scripting languages is another matter even if you ask for a dual interface (that applies within Visual Studio as well as by CMUD). It turned out to be easier for me to build a skeleton COM library in Visual Studio (C++) 6 and then import it into Visual Studio 2012 than to get VS 2012 to just produce the library by itself. Maybe I was doing something wrong but the steps seemed quite similar. Compiling to 32 bit XP-compatible code didn't help.

If you don't mind dragging around the .NET framework, producing a COM component in VB.net does work (and I assume C#; I used VB.NET so the test code would be vbscript equivalent). That .NET component is able to early bind or late bind to whatever other components you need.

When testing, even after #UNVAR'ing the reference to the last COM object in CMUD does not unload/release the library (which means that you can't recompile it without closing CMUD). Reference:
http://forums.zuggsoft.com/forums/viewtopic.php?t=17226
I do not believe that this is a problem with CMUD; I see the same behavior within Visual Studio itself (though when running a calling application in debug mode I think VS "cheats" by actually using the equivalent of another process, which does end and release the library after the debugging session is stopped).

The CMUD %comget doesn't just work with properties; it also works with functions/methods.

One other comment- I had a bit of trouble accessing an existing CMud application object: creating a new one returns a reference but the call for an existing one fails even if CMUD is already running.
Reply with quote
Tarn
GURU


Joined: 10 Oct 2000
Posts: 867
Location: USA

PostPosted: Mon Apr 15, 2013 4:57 am   
 
Followup:

Creating the COM object works as expected:
#VAR testinstance {%comcreate("TestLib.CTestClass")}

One more argument than you might expect must be passed in the case of a function (CMUD has %comget() but not a function specifically to invoke a method which returns a value, so the extra arg is probably a side effect of that).

#var tmp %comget(testinstance,"aaa","bbb","ccc","ddd","???")
works in response to the compiled call
STDMETHODIMP CTestClass::execcmd(BSTR dat1, BSTR dat2, BSTR Arg1, BSTR Arg2, BSTR* Arg3)
where Arg3 is really the return value of the COM call as seen in the scripting language (the C style return being the success/failure of the function at the COM API level).

The return value works properly and is stored in tmp.

I did have a problem with passing variable arguments into COM calls, for example
#var tmp %comget(delmea,"aaa","bbb","ccc",%concat(@tmpinput,":"),"???")

Having located the other calls, triggers, and variables related to the DLL in a class it silently failed when tmpinput was a top level variable but succeeded if it was in the same class even though the variable storing the COM class instance was top level.

So, data in and data out. I could put together a demo package for C++ if anyone's interested (the normal .NET languages like VB/C# being much easier- just creating the project and adding calls as normal seems to work).
Reply with quote
Anaristos
Sorcerer


Joined: 17 Jul 2007
Posts: 821
Location: California

PostPosted: Thu Jun 06, 2013 4:36 am   
 
I got around the release problem by making a call to my COM object manager in the OnExit event:
The C#-side code looks like this:
Code:

public void stop()
        {
            MessageBox.Show(Properties.Settings.Default.ExitMessage);

            sess = null;

            cmud = null;

            fr = null;

            ms = null;

            mw = null;

            rl = null;

            GC.Collect();

            GC.WaitForPendingFinalizers();

            GC.Collect();

            GC.WaitForPendingFinalizers();

            GC.Collect();

            GC.WaitForPendingFinalizers();

            GC.Collect();

            GC.WaitForPendingFinalizers();

            GC.Collect();

            GC.WaitForPendingFinalizers();

            GC.Collect();

            GC.WaitForPendingFinalizers();
        }

You have to call the garbage collector once for each COM variable. In the case above I have 6, so I call GC 6 times.
_________________
Sic itur ad astra.
Reply with quote
Tarn
GURU


Joined: 10 Oct 2000
Posts: 867
Location: USA

PostPosted: Fri Jun 07, 2013 1:55 am   
 
Anaristos wrote:

You have to call the garbage collector once for each COM variable. In the case above I have 6, so I call GC 6 times.


Thanks for the pointer. I'll look and see if the cleanup is being ignored at my end.
Reply with quote
Display posts from previous:   
Post new topic   Reply to topic     Home » Forums » CMUD General Discussion 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