Win32 Linked-In Drivers and A Project Idea

Posted: June 18th, 2009 | Author: kevin | Filed under: Erlang | 5 Comments »

I’ve been living in linked-in driver land for the past few weeks. I guess that’s what I get for publishing basic_erl_driver. It’s been interesting work so I certainly haven’t minded doing it.

Well, I didn’t mind it until I had to build one of my drivers on Windows. It’s been a long time since I’ve done much Win32 development but I used to know my way around Visual C++ pretty well. “I used to do this shit for a living. How hard could this be?”, I thought to myself.

Three words: famous last words.

Three more words: C++, linker, XML.

Two final words: sheer frustration.

After wrestling with Visual Studio Express C++ Edition 9.0 (or whatever crazy name MS uses) for a day and a half I finally have a working driver. Here’s the nuggets o’ knowledge I learned along the way. These notes assume you’re porting a working driver from OS X/Linux/BSD to Windows although most of them are applicable if you’re starting from scratch on Windows, too. They also assume you’re building code from inside of Visual Studio because, frankly, I don’t care enough about Windows to figure out nmake, too.

  • Start with a blank Win32 DLL project. Don’t let Visual Studio create stdafx and friends. Down that path lies madness. You’re much better off to create a blank project and import your code.
  • Add the erts-<version_number>/include directory to your project’s include path. You’ll need this so the compiler can resolve erl_driver.h.
  • Don’t forget to include string.h before erl_driver.h. erl_driver.h uses memcpy() without including string.h. Including string.h first will fix a compiler warning and a possible runtime crash.
  • Very Important: Right-click your project and navigate to the Linker -> Manifest File option. Enter this magical text into the Additional Manifest Dependencies field:
    type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processArchitecture='x86' publicKeyToken='1fc8b3b9a1e183b'
    

    I believe this tells the compiler to link the DLL with the Visual C++ 9.0 runtime. This is the equivalent of the C stdlib on other platforms, I think. Erlang will be unable to load your driver if you skip this step.


  • Observation: Who in their right fucking mind thought it was a good idea to add XML descriptors to the link step of building a C library?! I take back every bad thing I’ve ever said about Java’s use of XML. SOAP, with all of its angle brackety warts, almost looks sane in comparison.


  • With the previous step accomplished you’ll need to distribute the VC++ runtime with your driver. Luckily, MS provides the code in a redistributable form inside the Microsoft Visual Studio 9.0\VC\redist\x86 directory structure. Grab all of the files in there and plop them into the same directory as your driver’s DLL file.

There are probably better ways to accomplish the same goal given my dated platform knowledge. If you know of a better way to do this, please drop a comment and set me straight!

One of the drivers I’ve been working on is to allow SpiderMonkey to interface with Erlang. I’ve asked and am waiting for permission from my client to open source the code since I think it’d be generally useful. If that doesn’t pan out I’m strongly considering doing another driver — open source from the beginning — to interface with V8 or possibly WebKit’s engine. I’ve got some ideas on how JSON could smooth the interop between the two languages. Anyone up for either working on or sponsoring work on this?


Hands-On Erlang Cancelled

Posted: June 12th, 2009 | Author: kevin | Filed under: Business, Erlang | 1 Comment »

Due to a host of sour economic factors I’ve decided to cancel the Hands-On Erlang training class scheduled for mid-July in Chicago. All registered attendees will be receiving a complete refund by the end of today.

I’d like to thank the attendees who did enroll and everyone else who took the time to share their thoughts about training with me. While this isn’t the outcome I wanted the entire process has been a learning experience.

I am working on some alternative training and code review ideas which I hope to announce in the next few weeks.


It’s erlounge RDU time again

Posted: June 8th, 2009 | Author: kevin | Filed under: Erlang, Meetup | No Comments »

Wow. Another month has gone by and it’s time for another erlounge. Things have gotten a bit stale of late and I’ve no-one to blame but myself. It’s time I fixed that.

So.

This month, and subsequent months, we’re going to start splitting the meetings into two parts. The first, lasting 30-45 minutes will be a directed learning session focusing on some aspect of Erlang. This month we’ll focus on the basics of Erlang, getting it installed and getting acquainted with the syntax. In subsequent months we’ll move onto writing concurrent programs and finally exploring the power of distributed Erlang.

The second half of the meeting, lasting for at least 30 minutes, will be an informal session where people can continue working on programming exercises, socialize, or give a 5-10 minute lightning talk about something cool they’re doing with Erlang. We’ve got a small but growing Erlang community who’s doing some pretty cool stuff like Mark Imbriaco who put Erlang to work at 37 Signals and Sean Cribbs who’s written a Twitter bot in Erlang.

Click here to get more info about the meetup and RSVP.


Alternate DB slides are up!

Posted: June 3rd, 2009 | Author: kevin | Filed under: Talks | No Comments »

Thanks to Matthew Bass (and no thanks to my procrastination) the slides to the “Alternate Databases: CouchDB & Redis” talk I gave at raleigh.rb are up. Click the previous link to download them in PDF form.

I’ve tarred up my PDF slides along with the code for the two Sinatra apps I used during the presentation. The tarball is available here.


Erlang Trick O’ The Day

Posted: June 2nd, 2009 | Author: kevin | Filed under: Erlang | No Comments »

I’ve been researching Erlang <-> Javascript integration for a client project and decided to take a look at how CouchDB integrates with Spidermonkey. Along the way I found the couch_os_process:init/1 function:

init([Command, Options, PortOptions]) ->
    case code:priv_dir(couch) of
    {error, bad_name} ->
        % small hack, in dev mode "app" is couchdb. Fixing requires renaming
        % src/couch to src/couch. Not really worth the hassle.-Damien
        PrivDir = code:priv_dir(couchdb);
    PrivDir -> ok
    end,
    Spawnkiller = filename:join(PrivDir, "couchspawnkillable"),
    BaseProc = #os_proc{
        command=Command,
        port=open_port({spawn, Spawnkiller ++ " " ++ Command}, PortOptions),
        writer=fun writejson/2,
        reader=fun readjson/1
    },
    KillCmd = readline(BaseProc),
    Pid = self(),
    spawn(fun() ->
            % this ensure the real os process is killed when this process dies.
            erlang:monitor(process, Pid),
            receive _ -> ok end,
            os:cmd(?b2l(KillCmd))
        end),
    OsProc =
    lists:foldl(fun(Opt, Proc) ->
        case Opt of
        {writer, Writer} when is_function(Writer) ->
            Proc#os_proc{writer=Writer};
        {reader, Reader} when is_function(Reader) ->
            Proc#os_proc{reader=Reader};
        {timeout, TimeOut} when is_integer(TimeOut) ->
            Proc#os_proc{timeout=TimeOut}
        end
    end, BaseProc, Options),
    {ok, OsProc}.

The neat bit is the call to list:foldl/3 at the end of the function. It folds over a list of configuration options and pops them into an Erlang record. I would’ve never thought to use a fold this way. Neat!