Joe White’s Blog

Life, .NET, and Cats


Archive for January, 2007

ReSharper, day 0: Basics and installation

Wednesday, January 31st, 2007

I figured that, before I got too far into my 31 Days of ReSharper, I’d cover the dull stuff that nevertheless is worth covering. Feel free to skip ahead to Day 1 (though if you do install ReSharper, you might want to at least skim this post).

IDEs and versions

The latest versions of ReSharper will only work with Visual Studio 2005. There’s an older version still available that works for Visual Studio 2003, but it doesn’t have all the coolest features.

As of this writing, the latest version of ReSharper (which came out less than a week ago) was 2.5.1. It fixed several minor bugs in 2.5, which means I have a little less material than I’d figured on, since I’d been planning to talk about how to work around some of the annoyances. On the other hand, 2.5.1 seems to have broken a couple of minor things that worked in 2.5 (which I’ve already reported to them).

Stuff to know about installation

Be warned: the first time you install ReSharper, it will prompt you to install a Visual Studio hotfix. This takes for-freaking-ever. It’s been a while since we installed it on our work PCs, so I don’t remember how long it took there; but I recently installed it on my home laptop, and it took (no kidding) more than four hours. Granted, my home laptop is only an 850 MHz with 256 MB of RAM, but still. Four hours. Just so you know.

(Yes, ReSharper is worth the install time. But you might want to start the install fifteen minutes before you leave work for the day, so you can click all the Yeses and then go home. ReSharper will be ready to install the next morning.)

Installing help (or not)

ReSharper’s installation wizard will ask whether you want to install its Help. They warn you that this will take a long time because they have to rebuild the indexes for all the MSDN help on your machine.

They’re not kidding about it taking a long time; it makes installation take probably half an hour or so (and that’s on our beefy 3GHz work PCs with 2 GB of RAM).

But… I don’t get it. None of ReSharper’s dialogs have Help buttons. None of them even respond to F1. And when I bring up Help from Visual Studio, I have yet to be able to find any ReSharper help topics in there. So I’m not sure just exactly what Help they’re installing!

So for ReSharper 2.5.1 at least, I’d recommend not checking the box to install Help. There doesn’t seem to be any point.

Stuff on their Web site

Their support is quite responsive. As I was writing these articles, several times I was tempted to write “Now, it would be so much cooler if ReSharper could do such-and-so…” But each time, I made myself stop writing, went to their Web site, and sent them a bug report or an enhancement request. They’re really good about responding — usually I hear something back within hours. Even if it’s “we’ll add this to our list”, it’s good to get that quick response back.

And one time, a month or two ago, their response was “We’ve added that feature; it’s in the update that’s coming out later this week.” Probably they had already added it before I even asked, but still, it’s pretty cool (and rare) for a company to be that communicative about bug reports and feature requests.

Blog event: The 31 Days of ReSharper

Wednesday, January 31st, 2007

Note: This is about ReSharper version 2.5. R# is currently up to version 6, and has loads more stuff than I talk about here. So think of this as just the briefest introduction to what ReSharper can do.

ReSharper is a Visual Studio add-in that adds refactorings (many more than VS 2005 ships with), code cleanup, and a bunch of other conveniences. I tried downloading it a couple of years ago, opened the project we’d been working on, and it crashed. A lot has changed since then.

A few months ago, we looked at it again, and we liked what we saw. We bought a copy for everyone in the department. None of us wants to develop in Delphi anymore. (Granted, the lack of ReSharper is only one reason among many, but it’s a big one. Delphi can’t even pull off a rename refactoring, for crying out loud.)

JetBrains, the guys who make ReSharper, have a lot of info on their Web site that shows off some of the ReSharper features. But I think it’s a lot to absorb in one sitting. And besides, it could use the point-of-view of an actual, happy customer, saying “These are my absolute favorite features” instead of the complete laundry list. So I’m setting aside February on my blog for the “31 Days of ReSharper”.

Yes, I know there are only 28 days in February. But ReSharper is just that cool.

All our Visual Studio work is in C# (except for a tiny bit of C++, but ReSharper doesn’t do much for C++). So all my examples will be based around C#. ReSharper does also have a few refactorings for VB.NET, but I don’t know how extensive.

Here’s the list of the articles so far:

Marshaling Indy

Thursday, January 18th, 2007

We’ve got some TCP/IP client/server apps. They use a custom protocol that looks a bit like HTTP, but isn’t quite, for complicated reasons.

At present, we use Indy for all of our networking code. There are a lot of reasons for this, some of which went away over time, but the biggest reasons are (a) it’s a solid network library for Delphi, which doesn’t otherwise ship with any networking libraries beyond the Windows API, and (b) its server components are multithreaded right out of the box. Oh, and (c) it’s free.

We use the VCL version of Indy for both Win32 and .NET, because the all-.NET version didn’t exist when we started. It works quite nicely on both sides. Or did, until we tried to get all exotic.

Recently, we decided to try doing some interop between our Win32 DUnit tests and our .NET TCP server. Basically, our tests would create the server object and tell it to start listening for connections; would connect to it and do stuff; and then would shut down the server object. This would let us run end-to-end tests without actually needing to install our Windows service on the automated-build machine.

Sounds great. We wrote a C++ DLL to translate between the unmanaged and managed code, gave it a couple of exports, and fired it up. It crashed.

We tried debugging it. It died at the beginning of our server class, which descended from the Indy TCP server class. Apparently the blowup happened when our class called the inherited constructor.

I was the odd man out earlier in the week, so I played around with Hydra, to see if we just hadn’t done the C++ stuff right (or if the RemObjects people knew things we didn’t). I wrote a Hydra plug-in in .NET that let me create and shut down the server socket. This didn’t crash, but it didn’t work either: when I tried to write an app to connect to the server, it would connect and then immediately disconnect.

Weird.

Somewhere in the mix of .NET 2.0, unmanaged-to-managed interop, P/Invoked socket API calls, TThread-based threading code in .NET, and who knows what else, there be monsters. Indy, apparently, does not like interop.

And I confirmed that it was Indy, by writing my own multithreaded server socket. It worked just dandy in Hydra.

My multithreaded server was just proof-of-concept, of course; not ready for production use. We wound up doing something else. But I took some notes on what was involved in getting a multithreaded server up and running, and will probably elaborate on it and blog some of it in the future.

(Actually, getting it up and running isn’t that hard. It’s shutting it down that’s the problem.)

Hydra update: importing interfaces

Thursday, January 18th, 2007

It sounds like Hydra documentation will be forthcoming in a month or so (they shipped Hydra 3 last month, and they said they didn’t think the docs were worth delaying two months for, so the math works out to about a month left). In the meantime, importing interfaces using Hydra turns out to be easy.

In Delphi, there’s a “Hydra” menu in the menu bar (who’da thunk it?), and one of the menu items lets you browse to a .NET assembly and select which interfaces you want to import, at which point it creates a Win32 unit for you. If you do it again, it replaces the unit it generated the first time, which is good.

The IDE menu item is kind of nice to have, although I’d also want a command-line tool that I can tie into a rakefile or something, so I know the two sides don’t ever get out of sync. I’ve posted to their newsgroups asking if they have such a thing. If they don’t, I’ll probably bug them to write one. (grin)

Your .NET interface must descend from IHYCrossPlatformInterface, and must have a Guid attribute; otherwise the tool won’t import it. String return types seem to translate quite nicely, and I assume they work; they look about right. There are rumors that you can marshal complicated types like records if you write the MarshalAs stuff yourself; I’m not sure how that works.

There’s also a similar menu item in Visual Studio, which will read Delphi code and generate a corresponding .NET interface. I haven’t tried it yet, but it’s in the Tools > Hydra submenu.

The various ways to call from Win32 into .NET

Wednesday, January 17th, 2007

We’ve got several major applications written in Delphi, and several newer projects written in C#. And they need to talk to each other.

There are several ways for unmanaged Win32 code to talk to managed .NET code, and we currently use, or have used, most of them:

  • We have a couple of C# Windows services that run TCP/IP servers, and Delphi clients that connect to them.
  • We have a C# application that reads from Console.Input and writes to Console.Output, and a Delphi application that launches it and assigns pipes for its standard input and output handles. (If you’re thinking of doing this, see Console out from a non-console app for an interesting bit of info.)
  • At one point, we had a .NET assembly that registered some of its objects as COM objects, and a Delphi DLL that imported and used those type libraries. We do not do this anymore. To say that versioning is a bloody screaming nightmare doesn’t really do it justice. (Just try getting two different versions of the same app installed on a QA or client-support machine at the same time, when COM object registrations are machine-global.)
  • We have a C++ DLL that has unmanaged exports and instantiates managed objects inside unmanaged C++ class wrappers, and then exposes them via flat DLL exports. Sam has blogged about this already. It’s painful to marshal anything but the simplest of types, and you need to be a COM guru just to figure out who’s responsible for freeing strings, but it’s doable. (You can also do Delphi for .NET libraries with unmanaged exports; it’s pretty much the same thing.)

I recently stumbled across another option: RemObjects Hydra. Hydra was originally a plug-in framework for Delphi/Win32. But as of Hydra 3, which was released about a month ago, you can write the host app in either Win32 or .NET, and you can write the plug-in in either Win32 or .NET. So basically, you get total interop, without needing to do anything very ugly to get it. Sounds good so far!

What looks really cool (though I haven’t tried it yet) is that you can write a GUI frame in Delphi, and embed it into a .NET GUI; or vice versa, writing a UserControl in .NET and embedding it into a Win32 GUI. That’s not something you could do with just C++ glue. Without Hydra, that would probably take (shudder) COM. They even claim to have something that will let you use VCL TActions in a .NET app.

Hydra works by passing interfaces back and forth between Win32 and .NET. They’ve got a tool that will parse Delphi code and generate the corresponding .NET interface, and they’ve got something that will read .NET metadata and generate the corresponding Delphi interface, and make them compatible so you can just pass the interfaces back and forth and it all works.

That’s the idea, anyway. I haven’t used either of these translation tools. I haven’t even found them yet, because they don’t bother to document them.

They don’t bother to document much of anything. They’ve got an article on their Web site that talks in general about Hydra’s features, and another that shows how to use Hydra to embed simple GUI frames, but nothing about actually doing interesting work by calling actual functions with actual parameters. They do have a handful of samples in the download, but there’s one I can’t even open because I haven’t purchased all the third-party Delphi controls it requires, and I haven’t found any yet that use custom interfaces.

What I’ve seen does work, mind you, and it’s a far sight nicer than C++ glue. I’ve already had a chance to figure out a lot of the gotchas (like the crash on exit with a nice, friendly “Interface cast not supported” if you free things in the wrong order). However, what I’ve actually used is only a small part of what Hydra says it can do, and I don’t know if it’s enough to justify the $500-per-seat entry fee.

Coroutines

Thursday, January 11th, 2007

I’ve written a coroutine library for C#, which I intend to use in my video game. (I plan to open-source it in the future, after I’ve filed the necessary paperwork with my employer.)

So what’s a coroutine?

I’ve seen several conflicting definitions. In my implementation at least, a coroutine is a method that can yield.

Sounds a lot like C# 2.0’s iterators, doesn’t it? The difference is that C# iterators are restricted to being a single method; the “yield return”(s) must occur inside that method. You can’t do an Extract Method on a chunk of code that includes a “yield return”. (And because of the way they’re implemented — with a codegenned state machine — this limitation is probably permanent. The stack issues are too messy to deal with this way.)

With coroutines, the yield can be extracted into another method. You can even use recursion. Each coroutine has its own call stack, so you can do pretty much whatever you want. When you call the Yield() method, you’re instantly zapped all the way back to whoever originally called into the coroutine. The next time someone calls into the coroutine, you’re zapped back to wherever you were when you yielded, call stack and all.

What are they good for?

In my game, I’m going to have something like this:

Actor bob = new Actor("bob.png");
Coroutines.Add(new Coroutine(delegate {
    bob.WalkNorth();
    bob.WalkWest();
    bob.WalkSouth();
    bob.WalkEast();
}));

This will put a guy on the screen who walks in circles. (Okay, squares.) The various Walk() methods will be implemented something like this (pseudocode):

loop
    move the sprite on the screen
    yield
until we've moved the requisite distance

The program’s main work happens in the Paint event of the main user control. Once I implement coroutines, Paint will loop through all the registered coroutines, executing each one until it yields, then moving on to the next coroutine in the list. It’s really just cooperative multitasking. All the animation — wandering NPCs, flickering torches, etc. — will be, if all goes well, handled by coroutines. Which means, it’ll be a piece of cake to add a new piece of animation.

I’ll even be able to use coroutines to implement the main user-input loop, something like this:

Coroutines.Add(new Coroutine(delegate {
    if (IsKeyPressed(Keys.Up))
        Hero.WalkNorth();
    else if (IsKeyPressed(Keys.Down))
        Hero.WalkSouth();
    else if (IsKeyPressed(Keys.Left))
        Hero.WalkWest();
    else if (IsKeyPressed(Keys.Right))
        Hero.WalkEast();
}));

If I can swing it, I’ll even do cutscenes as coroutines. When it comes time to do a pre-scripted scene, I’ll plug in a “cutscene” coroutine, at which point the Paint event will run only the cutscene, ignoring all the other coroutines until the cutscene is done. So all the action freezes in its tracks, except what’s specified in the cutscene script:

PlayCutscene(new Coroutine(delegate {
    Hero.WalkNorth();
    Hero.Say("You'll never get away with this, Bad Guy!");
    BadGuy.TurnAroundSlowly();
    BadGuy.WalkSouth();
    BadGuy.LaughEvilly();
    BadGuy.Say("You fools think you can stop me? Taste my magic!");
    BadGuy.CastLightningBolt();
    Hero.SlumpToTheFloor();
    BadGuy.LaughEvilly();
    BadGuy.TeleportAway();
}));

How are they implemented?


I originally, a couple of years ago, was thinking about using fibers to implement coroutines. (A fiber is much like a thread, with its own call stack and everything. The difference is in scheduling. Threads are preemptively scheduled by the OS, and all appear to be running at the same time. Fibers are manually scheduled by your app, so you decide exactly when they run and when they stop. See Raymond Chen’s posts, “Using fibers to simplify enumerators [Part 1] [Part 2] [Part 3]”.)

Fibers are ideal for coroutines. When you want to call the coroutine, you just swap in a different fiber (with its own call stack, thus putting you right back where you were when you yielded), and when you want to yield, you swap in the original fiber (and its call stack, thus putting you right back at the caller).

The downside is that your runtime library (the C runtime, or the .NET runtime, or whatever) needs to be fully fiber-aware. Most aren’t. There’s a lot of potential problems lurking here (see Raymond Chen’s dire warnings about fibers). The .NET runtime was not fiber-aware, at least a couple of years ago when I e-mailed some of the developers. (It might be more so now — I think MS SQL Server uses fibers internally, and it can host the CLR — but I wouldn’t want to count on it working in a normal .NET app, without MSSQL’s specially-tuned CLR host.)

So I cheat. I use threads, but I only let one of them run at a time. When I create a coroutine, I create a thread, and then do some handshaking that ends with a call to Monitor.Wait(), which blocks the coroutine thread — it won’t run anymore until it’s unblocked. When it’s time to call into the coroutine, I do a handoff that ends with the calling thread blocked, and the coroutine thread runnable. Same kind of handoff on the way back.

Those handoffs are kind of expensive, compared with other implementations. If you need speed, you’ll want to write your own state machine, and avoid all this context switching. (Or you’ll want to use a fiber-aware runtime — switching fibers is pretty cheap.) But if you want expressive code, I think coroutines hold some promise.


Joe White's Blog copyright © 2004-2011. Portions of the site layout use Yahoo! YUI Reset, Fonts, and Grids.
Proudly powered by WordPress. Entries (RSS) and Comments (RSS). Privacy policy