September, 2004

Posts
  • Eric Gunnerson's Compendium

    Puzzling through Erasure II

    • 24 Comments

    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.

  • Eric Gunnerson's Compendium

    DirectShow and C#

    • 19 Comments

    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:

    private T CreateComObject<T>(Guid guid) where T: class|
    {
        Type comType = Type.GetTypeFromCLSID(guid);
        object o = Activator.CreateInstance(comType);
        if (o == null)
            return null;

        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.

     

  • Eric Gunnerson's Compendium

    Aspiring Fred...

    • 17 Comments

    Fred
    n.
    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:

    1. It needed to have a compliant ride. My current bike has a steel frame (well, chrome - moly steel to be more precise), and such frames soak up bumps very well. Aluminum, on the other hand, does not, so it's not really in the running. That leaves either steel, titanium, or the new star on the block, carbon fiber.
    2. It needed to have a better drivetrain. I decided that Shimano Ultegra was my target. Despite the name, Ultegra is not "the ultimate" component group for Shimano - that niche is occupied by "Dura-Ace" - but it is light, strong, and well engineered.
    3. It needed to come with a triple chainring up front. This is so that I have a "granny ring" to help get up those steep slopes. More talented riders would have only two chainrings, usually of something like 53 and 39 teeth. A triple might come with 52/42/30 teeth, which means that the lowest ratio is 30/39, or about 25% lower than the double option, giving 25% more torque.
    4. It needs to look cool. If you're going to spend good money on a bike, you should at least like the looks.

    I headed out to Samamish Valley Cycles to start my search. After a bit of discussion, we settled on two likely bikes:

    • A Litespeed Firenze, their entry-level titanium, coming in a bit under 18 pounds (13 KiloPascals).
    • A Bianchi with a steel frame, whose name escapes me.

    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.

  • Eric Gunnerson's Compendium

    Reverse

    • 15 Comments

    Another way to "improve" your hand-eye coordination.

    Reverse

  • Eric Gunnerson's Compendium

    And so it ends...

    • 13 Comments

    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.

  • Eric Gunnerson's Compendium

    Mediterranean Medley

    • 13 Comments

    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:

    • 10 ounces good pasta.
      I like Barilla, which is good without being too expensive. Something small and chunky, like rotini, radiatore, route, or farfalle. Last time I used the red/green/white version.
    • 1 chicken breast
    • 4 slices proscuitto
      Domestic is cheaper, and works well. Proscuitto de Parma is wonderful, but a bit pricier. Don't get freaked out by the $15/pound price - you're only using 4 very thin slices.
    • 20 medium-sized white mushrooms
    • 1/2 jar roasted red bell peppers
      you can do this yourself, but it takes a gas flame (or a grill), and isn't really worth the effort. You can't get the right flavor from fresh red bell peppers.
    • 1 medium onion
    • 4 roma tomatos
    • 20 greek olives
      You need real olives for this, the american black olive won't really work. I like kalamata olives, and sometimes I get the mixture instead.
    • 1 clove garlic
    • 8 large leaves of fresh basil
      You can omit this if you must, but it helps the dish a fair bit.

    Directions:

    • Fill your pasta pot with water, and put it onto boil.
    • Slice the chicken breast into cubes of about 1 cm on a side. Spread out on a plate and sprinkle with a few pinches of salt. Mix so the salt is distributed evenly. This draws some fluid out of the chicken, which will then carmelize when you fry it.
    • Either wash your cutting board and knife or switch to a different one, to avoid those raw chicken nasties.
    • Stack up your proscuitto, and cut lengthwise into 1/4" strips. Put them together, and cut those so that you have little 1/4" square pieces of proscuitto. Set aside.
    • Dice the mushrooms, peppers, onions, and tomatos. I try to get them to the "uniform but still recognizable" stage, something around 3/8" max on a side.
    • Pit the olives (you *do* have an olive pitter, don't you?), and chop them. I don't go for much uniformity here - I like big chunks and small chunks, but you can do as you wish. Make sure they aren't whole, as their flavors won't mix as well.
    • Either put the garlic in your garlic press (the Zyliss Susi is the best), or chop and smash it really fine.
    • Stack the basil leaves on top of each other, slice them lengthwise into quarters, and roll them together and slice them into 1 cm strips. (If you didn't slice them lengthwise first, this would be a "chiffonade", but I think those strips are too long for this dish)
    • Okay, so now you're done with all the chopping, and like stir fry, that's where all the work is in this dish. Presumably along the way your pasta water boiled and you added the past with it. It will usually take about 7 or 8 minutes to finish the meal, so you'll want to make sure you get your pasta al dente at a reasonable time. The dish will hold for 4 or 5 minutes if you need to wait for the pasta.
    • Heat a 10" nonstick skillet over high heat. You want to get it pretty hot, but not "smokin hot". You may want to add a bit of cooking oil, but it will increase the mess slightly. Add the chicken. Your goal is to let the chicken sit on each face for a little while so that it will carmelize a bit, but make sure you give a stir every minute or so. I like to do the "toss move" where you tilt the pan down, slide the food to one end, get it to flip off the curved edge of the pan, and then catch it, because it gives you better mixing, but you may stir if you want. After you don't see any more raw chicken edges, try pushing your wooden spoon or spatula through a large piece - if it's cooked through, pull it off, and put the chicken on a plate. Return the empty pan to the heat.
    • Add the proscuitto to the pan. No oil will be needed. You're trying to get a little crispness on the proscuitto, both to improve the flavor, and to break the pieces apart (Proscuitto de Parma is stickier than most domestic versions). This should only take a minute or two. You don't want all of it to look "bacon crisp", but it's good if some of it does. Put the cooked proscuitto on the same plate as the chicken. If you have young kids, you might want to pull some of the chicken off so it doesn't get all "yucky" when you finish the dish.
    • Return the dish to the heat, and add a little olive oil. Don't scrape off the proscuitto parts that are left in the pan - that's the good stuff. Reduce heat to med-high. Add in the mushrooms, peppers, onion, and tomato. This is a pretty big amount for a 10" pan, so you'll need to keep it moving to keep it cooking well. Toss only if you're confident, or perhaps if you have a dog waiting for scraps. Cook about 4 minutes, until the mushrooms are tender but not too tender (the mushroom equivalent of al dente for pasta). Somewhere in this time period, you should add the garlic. Add it early if you want it to be somewhat muted, later if you want it to be brighter (I add it later). Make sure you get it mixed well into the dish. You'll start to accumulate a little liquid - that's a good thing.
    • Add the chicken and proscuitto back to the dish, and mix. Cook until heated. I do "the toss" here, but it's getting pretty heavy.
    • Remove from heat, add the basil, and mix.
    • Spoon over cooked pasta. You can decorate with some basil leaves if you'd like.
    • Serve with a nice rustic Italian bread.

    Serves 2-3

  • Eric Gunnerson's Compendium

    Group Blogs

    • 12 Comments

    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.

     

  • Eric Gunnerson's Compendium

    Blog Alerts

    • 9 Comments

    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.

  • Eric Gunnerson's Compendium

    Performance of Generics

    • 9 Comments

    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...

  • Eric Gunnerson's Compendium

    The power of snow...

    • 8 Comments

    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.

  • Eric Gunnerson's Compendium

    What's wrong with this code (COM Interop)?

    • 7 Comments

    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()));
    }

     

  • Eric Gunnerson's Compendium

    Work on the C# Team...

    • 7 Comments

    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

  • Eric Gunnerson's Compendium

    My First Inspection...

    • 6 Comments

    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:

    1. The dishwasher needs an air gap (also known as a vacuum breaker) on the outlet. Consider the following scenario: You have a big tub of dirty water in your laundry sink, and you're filling it from a faucent with a short length of hose that goes under the water. If the water pressure drops, the water flow could reverse, pulling the waste water back into the supply, causing havoc. There are several code rules tha prevent this from happening - for example, a faucet can't be below the top water line on a faucent - and an air gap on dishwashers prevents water from siphoning back.

      So, you may be asking, if I knew all this, why didn't I install an air gap. Well, when our kitchen in our main house - also in King county - was remodeled, they didn't put in an air gap, so I didn't put one in.

      So, this is an easy one to fix.
    2. The toilets need to be caulked along the front and sides.

      Also an easy one to fix, and the inspector was willing to pass the inspection if this was all he found.
    3. The on-demand water heater was missing a relief valve. If you have a gas water heater, you probably have something like this on top of it: 

    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...

  • Eric Gunnerson's Compendium

    Tom Peters Blog

    • 6 Comments

    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.

  • Eric Gunnerson's Compendium

    Halo: First Strike

    • 5 Comments

    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

  • Eric Gunnerson's Compendium

    COM wrappers in C# - the easy way

    • 3 Comments

    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).

  • Eric Gunnerson's Compendium

    Coming soon to a medicine cabinet near you...

    • 3 Comments

    Let's see... band aids... Motrin... Ah, here they are!

  • Eric Gunnerson's Compendium

    A song for you...

    • 3 Comments

    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.

  • Eric Gunnerson's Compendium

    More on DirectShow and C#

    • 2 Comments

    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.

  • Eric Gunnerson's Compendium

    Exactly what is "Over The Top"

    • 2 Comments

    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.

     

  • Eric Gunnerson's Compendium

    Now there's a limo...

    • 1 Comments

    Now there's a limo

  • Eric Gunnerson's Compendium

    Sojourner: An Insider's View of the Mars Pathfinder Mission

    • 1 Comments

    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.

  • Eric Gunnerson's Compendium

    Remotable Windows Media ActiveX Control

    • 1 Comments

    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.

  • Eric Gunnerson's Compendium

    [C# Chat] What's on your mind regarding C#?

    • 1 Comments
    September 23 - What's on your mind regarding C#?
  • Eric Gunnerson's Compendium

    A built-in stereo cabinet.

    • 1 Comments

    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.

     

Page 1 of 2 (26 items) 12