Bruce Eckel has some further thoughts about the use of erasure in Java generics.
Erasure is the way that Java gets generic types without adding VM support. When the developer writes something like:
List<Integer>
in Java generics, the compiler knows that this type can only contain an integer, but when the bytecodes are generated, the type is really:
List<Object>
This means that Java generics doesn't give you the performance benefit that .NET generics do - not only do you not have the ability to create generics on value types (not that surprising given that Java has previously not had boxing), but you still have typecasts in your generated code.
Advantages? Well, the advantage I always heard was that erasure meant that you could run on downlevel VMs, but it turns out that that isn't true. It does mean that it's much easier to write a 5.0 VM than it would be if an approach such as the .NET one was used.
The other advantage is that because the underlying object is really a List<Object>, it's possible to implement a wildcard feature in which you can write something like (and forgive me if my Java syntax is wrong):
List<?>
which means a List of anything. You can get away with this in erasure because everything's the same type under the covers, but it would be much more challenging in the .NET implementation because List<double> is very different than List<string>.
My personal opinion is that it's far more important to be able to have generics over value types and performant implementations than to support wildcards. In VS2003/C# V1.1, programmers sometimes need to ask the following question:
"Hmm, I need a list of integers here. Should I use an ArrayList, which is easy to write, or should I use my own IntegerList class, which is a bit harder to write, but performs better. Or should I use an array".
The fact that users need to consider that is bad, as is the fact that code contains all three options, and it's often hard to know why a specific option was chosen.
I'm currently in the "ramping up" phase of my job, and last week I spent a fair amount of time playing around with DirectShow from C#.
DirectShow is an interesting technology that provides a sort of "building block" approach to multimedia. You create a DirectShow graph, populate it with different filters, hook them together, and start the whole process in motion. DirectShow handles the mechanics of getting the different parts talking to each other so data can flow through the system.
If, for example, you wanted to capture some audio and save it to the disk in WMA format. You'd start with an audio input filter, which has an output pin. You'd wire that output pin to the input pin of a WMA encoder, and then wire the output pin of the encoder to the input pin of the FileStream filter, and that would give you the basic graph. Select which input you want, tell the graph to play, and your app is up and savin' data.
Want to add a little reverb? Hook in the reverb filter.
Video is similar - you hook things up together, and DShow handles passing things around. There's a cool workbench app named GraphEdit (graphedt.exe) that lets you graphically play around, and is a great way to find out what works before you write code.
All of this is explained quite well in "Programming Microsoft DirectShow for Digital Video and Television"
There are some managed DirectX wrappers in the DX9 SDK, but there aren't any available for DirectShow. I think I know why, but I'll save that for later...
I set out to try to use C# from DirectShow, to emulate some of the C++ samples. The first problem is defining the COM interfaces. I've spent some time trying to define interfaces by hand in the past, but that hasn't been very successful. I searched for a typelib, but didn't find one.
I did, however, find something that is a little better - the .IDL files. IDL files provide the definition of COM interfaces, and in this case are used to generate the C++ header files. They can also be used as input to MIDL, which produces a type library, which can be consumed by tlbimp to produce managed wrappers, which allows us all to go home early.
They can if they've been set up to do that. But this IDL wasn't authored to produce a typelib, so it doesn't generate one by default. To do that, you need a library statement, which tells MIDL what to put in the typelib. Here's what I put in an IDL file:
import "devenum.idl";import "axcore.idl";import "axextend.idl";
[uuid(22995cc9-e37e-4b96-9326-b418935ac4be),helpstring("DirectShow interfaces")]library DirectShow{ interface IFilterGraph; interface ICreateDevEnum; interface IGraphBuilder; interface ICaptureGraphBuilder2; interface IFileSinkFilter; interface IFileSinkFilter2; interface IAMAudioInputMixer;};
You have to have a GUID there for it to work.
When run through MIDL, this gave me the typelib, which gave me a wrapper with some of the types I needed. You'll also need to add quartz.dll from windows\system32, which does have type information, so that you can get some of the other types.
Once you've got that set up, you can start writing code. The C++ COM code in the samples is like most C++ COM code - ugly and hard to understand. But it's not that bad in C#.
To create a COM object, you need to write:
Type t = Type.GetTypeFromCLSID(guid);
IGraphBuilder graphBuilder = (IGraphBuilder) Activator.CreateInstance(t);
The guid is a Guid instance, and you get the Guid to use by looking in the include files or copying it from GraphEdit. That's a bit ugly, so I wrote this little helper function:
else return (T) o;}
Which then allows me just to write:
IGraphBuilder graphBuilder = CreateComObject<IGraphBuilder>(CLSID_FilterGraph);
That's a nice little use of a generic method.
Sometimes, you want an interface off an object rather than a new object. You can do that through a simple cast.
Up to this point, things are fairly easy, and it makes you wonder why there's no managed interface to this stuff. Some of the real power comes when you want to write a filter, which could do something convert a picture to grayscale. While one could write a filter in C#, one would have to be pretty daft to try it, given that there are lots of helper classes in C++ that you'd have to rewrite in C++ (ok, perhaps MC++ could help...). My guess is that that's why there are no managed wrappers.
Fredn.1) a person who spends a lot of money on his bike and clothing, but still can't ride
I decided a while back that my trusty old LeMond Tourmalet (named after a famous cycling climb often featured in the Tour de France, as most of LeMond's bikes are) was holding me back. Specifically, despite me dropping a number of well-placed hints, it still weighs as much as it always did, a portly 29 pounds. The lightest pro bikes are around 6.75 kg (33.5 hectares to you and me), which is roughly half of what the Tourmalet weighs, and there are a number of bikes that weigh less than 18 pounds (1.25 parsecs).
So, it was off to a LBS (local bike shop) to see what was out there. I had a few requirements:
I headed out to Samamish Valley Cycles to start my search. After a bit of discussion, we settled on two likely bikes:
I rode the Firenze first. It's very light with a low moment of inertial (ie light wheels), and rides wonderfully, though there is a certain springiness. I liked it a fair bit, but unfortunately, it only comes in a matte finish. I'm all for the artistry of nice welds and good machining, but silver is my least favorite color for vehicles, so this is a non-starter for me. Litespeed does make the Solano, which is a bit stiffer, and comes with a nice yellow paint job. I'm not sure if it's available with a triple or not, however.
The Bianchi was pretty forgettable. It rode like a slightly different version of my current bike - better, but not really better. So it's not on my list.
My next bike to try is the Trek 5200. Carbon fiber frame, just like the US Postal bike, blah, blah blah. It meets all my requirements, so I'll be trying to ride one in the next couple of weeks.
Another way to "improve" your hand-eye coordination.
Reverse
Nearly 10 years ago, when I was only 1E years old, I joined the Visual C++ compiler test team to test the new multiple rebuild feature. Since then, I was a lead for testing the whole C++ compiler, helped test a new compiler back end (aka optimizer), and spent the last big chunk of time working on C#, both as a test lead and as a PM.
Now, my Journey on the Circle of Life (actually, a more correct term would be the "Circle of Disciplines" as I move amongst the disciplines from Test to PM to Dev, but I think that "Circle of Disciplines" might have the wrong connotations to some...) continues as I leave the C# team to go to Movie Maker.
I'll be off next week, and likely will not be blogging much. I'm not sure what I'll be writing about in my new role - it's going to take me a while to ramp up and to figure out what I can talk about.
I like to cook, though I don't have much time to focus on it. I usually have one or two dishes that I'm working on, and since Jim Carson has been putting recipes on his blog, I figured I'd do one on mine as well. This one is pretty good if you use fresh ingredients.
Mediterranean Medley
Quantities are estimates, as I don't typically measure any of this.
Ingredients:
Directions:
Serves 2-3
Daniel wrote,
I am interested in your comment about not subscribing to group blogs. Why? Isn't it a good way to discover new blogs worth reading? Just curious...
I think it's important to differentiate between two types of blogs. The terms I use (which may or may not be generally accepted) are:
Aggregated blog
A blog that aggregates together the blogs of separate people, presenting them on one feed.
Group blog
A blog with posts written by several people.
I think aggregated blogs are okay, though I tend to read them on their web page to find out what I like rather than subscribe to them. They do tend to be pretty noisy, especially when there are a number of new bloggers, but if you can get by that, there may be some good people to subscribe to.
Group blogs are a different beast. In them, a group of people write articles for the same blog. ABlog is one, and there are a few that are run by Microsoft teams.
I don't think I've come across one yet that was any good. I read a blog to get a specific person's perspective, not to get the jumbled-together perspectives of a group of people. Group blogs also lack coherence, and most they are normally one-way.
In my mind, one of the points of having a blog is to engage in conversation. I read every comment that gets made on my blog. Sometimes I reply, sometimes I comment, sometimes I write a new blog entry. Sometimes I don't do anything, but the comment still effects what I do in the future.
That's because I have a sense of ownership around it, because it's *my* blog. It's just human nature to care more about something that has your name on it than something that has your team's name on it.
The C# team actually has a group blog for FAQ questions. It's much better than not getting that information out at all, but it has neither the personality nor the interaction of a personal blog. That's okay if it's an *adjunct* to other blogs, but not if it's the only one for a team. I'd read a general Apress blog devoted to new releases even if it were a group blog, because it would have a different goal.
My advice to everybody doing group blogs is to do aggregated blogs instead. Sure, it's more work, but the result is so much better.
I recently signed my blog up for the LiveMessage alert system. This means that, if you want, rather than having to goto my blog web page to see if there are new posts, you can get a notification directly.
If you're already using an RSS aggregator (SharpReader, RSS Bandit, NewGator, etc.), that this likely isn't of much interest to you.
All you need to do is click on the block below, and sign up. The downsides are that it's Passport based, and you have to agree to expose your email through your passport. Not a big deal for me, since I already have my email address published far and wide, but may be an issue for lots of others, since you can't say "expose my email address only to this site", nor can you use different addresses.
You can use IM or mobile notification rather than email and avoid this, but I'm pretty sure that the number of people who want to get an IM message when I write a new blog entry is considerably less than one, so I don't think this will be of much use.
What do you think of such a system? It doesn't really solve my "keep in touch with my family" goal, because I'd have to get them all signed up with passports and enrolled in the system.
Click below if you want to register.
Rico wrote a short post covering 6 questions about generics.
It has some good information in it, but I'm not sure that you should spend too much time thinking about the issues that he's talking about. Groups writing libraries inside Microsoft should take performance very seriously - if we provide a great library with poor performance, it doesn't have a lot of utility for customers. The problem that library writers have is that there isn't a small set of performance scenarios - performance matters all over the place, because it's hard to tell what customers are going to do with the library.
But for the majority of applications, this isn't the case. Performance is rarely dominated by small decisions, such as whether you use an ArrayList or a List<int> to store your data. It's usually dominated by algorithmic concerns - how you process data, how much redundant processing you're doing, etc. My experience is that the ability to be able to address these concerns is fairly well correlated with the resiliency of your code to change, which usually comes down to how clean and understandable the code is. If you have clean code and good tests, it is probably feasible to refactor your code to improve performance once you find out where the performance issues are.
Note that I'm not saying that you should put performance off until the end - that rarely works, as time at the end is fairly precious. I think you should focus on macro performance rather than micro performance.
Update: Rico wrote a short response...
We have a ski place in Skykomish. Given that it's only at 1000 feet of altitude and we don't get much snow at our house at about 300', you wouldn't think that there would be much snow at the ski place.
You would be wrong.
In February of the first winter, I was walking around, and came across a scrap of 2" ABS plastic. Hmm, must be left over from the construction. But why is it on top of the snow? And why is the end jagged?
Well, it turns out that it was one of the vent pipes from roof, broken off from the accumulated pressure.
It's hard to get a good estimate of how much weight there was from the snow above the vent, but my guess is that there was at least several hundred pounds pressing on that pipe.
I contacted a good roofer, and he put on some roof jacks - braces that attach to the metal roof, and guide the snow around the pipe. That worked fine for the winter of 2002-2003, when there was little snow. But as the water-filled paint stalactite and puddle on the hardwood that I found last weekend attests, it wasn't enough for last winter's snow, which totally ripped one of the jacks off.
After consulting with a roofer, I've decided to go for the "gold" cure. We (and by "we", I mean the roofer I hired) are going to pull off the roof panels, cut open the roof, and re-route the vent pipes so that they come out the ridge, like they would have if my plumber had clue1 about putting a roof on in snow country. It won't be cheap, but it will be done.
Oh, the joys of home ownership.
A special "COM Interop" edition of "What's Wrong with this code?"
This code is using some Windows Media interfaces to get the properties from a profile.
IWMMediaProps::GetMediaType() gets a _WMMediaType structure. Because there is optional format data that comes back, you have to call the method once to get the size, then again to get the actual data. You can assume that that extra data is a WAVEFORMATEX structure. In the C# world, the pbFormat field in _WMMediaType is an IntPtr.
Here's the code. There's something bad lurking there. I think I've given you enough information to figure it out.
IWMStreamConfig iStreamConfig = ...; // set somewhere else...DirectShow.IWMMediaProps mediaProperties = (DirectShow.IWMMediaProps) iStreamConfig;
uint typeSize = 0;mediaProperties.GetMediaType(null, ref typeSize); // call to get size
byte[] buffer = new byte[typeSize];mediaProperties.GetMediaType(buffer, ref typeSize); // call to fetch values
fixed (byte* pBuffer = buffer){ mediaType = *((DirectShow._WMMediaType*) pBuffer); waveFormatEx = *((DirectShow.WAVEFORMATEX*) (mediaType.pbFormat.ToPointer()));}
Jay writes about some openings to work on the C# team.
If you've never considered working at Microsoft, you might want to read http://blogs.msdn.com/jobsblog
We have a ski cabin up near Skykomish, a really small (~~ 200 people) town on Highway 2 towards Stevens Pass.
We had the builder build the shell for us - up through drywall and paint - and we've done all the finish work, including all the electrical, plumbing, kitchen, flooring (hardwood and tile), and all the finish carpentry. During the ski season, we typically go up Friday night or early Saturday, work on the house (it's really a house - "cabin" is a way to disambiguate) all day Saturday, and then ski on Sunday.
I've gotten tired of paying the fee to renew the permit, so I'm on a push to get the "Certificate of Occupancy", which means that King County is satisfied with the house. Last night I went up to the cabin so that I'd be there for the plumbing inspector.
The inspector - a really nice guy, by the way - found 3 deficiencies:
If your water heater burner didn't shut off, the water in it would boil, and as the pressure built, things would get ugly, in the "Fire Department takes you to the emergency room" sense. So, when my plumber put in our water heater, he forgot the valve, and that's something the inspector couldn't overlook. So, I'll need to spend a couple of hours sweating in the pressure relief valve and piping the outlet outside, and then I'll be able to get the signoff.
And then, on to the full inspection...
Tom Peters is an influential thinker on business and management, and I've been reading his stuff since the late 1980s. I think "In Search of Excellence" was the first book of his that I read.
He has a blog (well, a group blog, but I'm going to make an exception against my rule of not subscribing to group blogs this time). Here's an interesting post on The Power of Independent Thinking.
When I was in the library on Saturday, I came across a copy of Halo: First Strike by Eric Nylund.
I figured that since I had spent a ton of time playing the game, it would be worth it to spend a little time reading a Halo book. I didn't expect much - book adaptations from other media tend to be pretty bad.
Surprisingly, the book is pretty good. Nyland's writing isn't up to the standards of the Davids (Drake and Weber), but it's quite readable.
I also discovered something I didn't expect. Though I'd never thought about the Halo backstory very much, I was quite interested in it once I started reading the story. Since it covers the time between the destruction of Halo and the time when the covenant reaches Earth, it's a good way to get primed for Halo 2.
Recommended
Mihailik had a good suggestion for how to do COM interop in C# the the comments to a previous post that I'd like to share.
In many cases, TLBIMP produces a wrapper that can be used directly, and that's certainly the easiest way to do things.
But sometimes it doesn't make the right choice in how to express an interface. I ran into two situations yesterday:
In the first one, tlbimp produced an interface where an output string got the type of "ref ushort". In the second one, the designers of the interface decided that they would type a parameter as a byte* to point to lots of different kinds of data, and tlbimp typed that as "ref byte".
So, it meant I needed to tweak the parameters on the interface definitions. The hard way to do this is to write the interface definitions by hand. It's not much fun. Or, you can run ildasm, make the tweak, and then use ilasm. Also not a lot of fun.
The easy way - that Mihailik recommended - was to use Lutz Roeder's excellent .NET reflector, point it at the assembly that TLBIMP generated, and then use the disassembly feature of Reflector to get C# code. Paste the code into a source file, make the necessary tweaks, and Bob's your uncle.
With a few caveats...
First, the full richness of COM cannot be expressed in C#, so it's possible that you'll come across an interface where the C# version doesn't work correctly.
Second, you may come across some little thing's that don't quite mesh with C# syntax. I came across a case where an attribute wasn't legal in C#, and several where a derived interface restated the base interface's members (taken care of by adding a "new" to the derived interface definition).
Let's see... band aids... Motrin... Ah, here they are!
I usually don't link to Rory, for the simple reason that he's funnier than I am, and I hate that.
But I'm going to make an exception for the song that Rory composed about Chris Sells going to Burning Man.
It's good he works for Microsoft now. I shudder to think what he could accomplish if he turned his talents towards evil.
To respond to a few of the comments on my first post
One person asked whether MM would be rewritten to use the media foundation classes in LH. I'm not really the right person to comment on that - that would seem to be a marketing function. In the C# team, I did some quasi-marketing stuff and knew what I could talk about and not talk about, but I'm not there yet here, and my initial read is that the Windows division has a different bar than the developer division on such things.
On the question about my use of generic methods - yes, I could have just use a normal method, and for my use, there's not much reason to prefer one over the other, though there could be cases where using Activator.CreateInstance<T> was preferable. But in general, I prefer the type to come out of the function rather than having to coerce it in my code, and I think CreateComObject<X> is a bit more readable.
On DirectShow.NET - yes, I know of its existence, and it's possible that I could get permission to use it, but in this case, writing my own is easier than getting permission. Also, the whole point was for me to spend some time writing code, and having me write it all furthered that goal. I have no idea what the DirectShow team plans in the longer term - you'd have to take it up with them.
Finally, on the subject of getting "dirty" results out of IDL->MIDL->TLBIMP->Assembly, is is true that it is some COM interfaces can be fully expressed in C#, but there are some interfaces that can't. I might consider converting them to C# definitions in the future, but there isn't necessarily much reason to do so.
On the Northwest Rocketry mailing list, there are sometimes discussion as to what qualifies as "over the top".
Here's an example in a related field.
Now there's a limo
I just finished reading Sojourner: An Insider's View of the Mars Pathfinder Mission
It's written by Andrew Mishkin, a systems engineer at JPL, and gives an insider's view into how the Sojourner team managed to design, build, staff, and operate the rover for $25 million. It's a very engaging read, covering both the design and the team challenges that they faced.
A great accomplishment, all controlled by an 8085 processor, Sojourner set the stage for Spirit and Opportunity, still roving on a planet near you.
Recommended.
A while back, I posted about my problems getting this to work, and I got an email back from somebody internal who had something that works.
I got an email from somebody inside of Microsoft who had solved the problem by wrapping the Windows Media Player ActiveX control in another control, and then using that control from C#. I got permission to post the code, though I should warn you that it's fairly untested.
I've been spending some time catching up on a few house things this week.
Tuesday and Wednesday I spent building a stereo cabinet. I'm lucky enough to have a closet in my family room that backs to a storage area, so I've been rebuilding the closet to be dedicated to holding my audio/video equipment. I'll be triming it out to match the design of my A/V center.
(as an aside, who does the design for A/V furniture, anyway? Ours has a 20" by 30" space on each side of the TV, but there is no provision for ventilation, and if your components don't all fit on one side (mine wouldn't), you have to run cables across from one side to another. No thanks).
So, the closet is done, but I now need shelves to go into it. I don't like any of the premade racks you can buy (and they're really pricey), so I decided to build my own. I started with two sheets of 3/4" shop-grade birch plywood, ripped to the proper width on the panel saw at Dunn Lumber (If you need plywood cut, this is a great way to do it). My tablesaw is up at the cabin (more on that later), so I built a jig to cut the top and bottom and shelves to the right side using my circular saw. The cabinet carcass is together now (using glue, biscuits, and screws), and I've started putting the hardwood fronts on the shelves (they'll be painted but you can't get a good finish on the front of plywood).
Next is to finish clamping up the shelves, sand up everything, stain and finish the carcass, and prime and paint the shelves black (to match the way the entertainment center is finished). Once I get that done, I can install it and move the components into it from my current cabinet. Then, I'll build a face frame and door with smoked glass to go on the front, and attach it to the carcass.
I'll post pictures when this is all done.