Thursday, August 7, 2008

Had a really fun evening...

Had a really fun evening tonight and went to the George Eastman house and then to Charlie's Frog Pond

Powered by Jott

kitty.cat

wow... this is really cute.

source: http://kitty.cat/

Tuesday, August 5, 2008

Jott from www.jott.com....

Jott from www.jott.com. I believe it's my new best friend.

Powered by Jott

Sunday, August 3, 2008

IPC

At work the other day I had to come up with a creative solution to a linking problem. I had a library from a 3rd party vendor that used one set of C++ libraries, and I had our code that used another set of C++ libraries. Unfortunately these libraries are incompatible with each other. This is because they both define the same (or at least some of the same) symbols. i.e. they both define std::string, std::cout, std::map and so on. The problem is that they do not have the same feature set (they can't be blindly interchanged) so we can't just recompile with the other library set and vice versa. 

Either way, my managers just wanted it done. They wanted us to use theses libraries, no matter what, A.S.A.P. The only way I knew of to compile anything with those shared libraries was to have another heavy weight process. This was surprisingly much easier than I originally imagined. 

My original intent was to develop our code as if we could use their library without any problems. Then, create functions that resolve all the symbols that are "missing" when I try to compile. These functions will use one form or another of IPC to make the function calls to the other heavy weight process to do what we originally intended. Here's an example of how I did it.

The main process defines all the missing symbols as functions with the exact same signature.
I define an enumerated type with the names (Almost) of all the functions that can be called.
enum messageNames { fun1, fun2, fun3 };

I define some shared data types (structures) that will be passed between the sender and receiver. These types will be based on the passed data types to be sent between the function calls. i.e. 
typedef struct _my_sending_data_ {
messageNames message;
char key[100];
int index;
float some_data[50];
...
} MySendingData;

Now, do the same thing for data that will be returned from the functions

typedef struct _my_receiving_data_ {
char value[100];
int error_code;
float ret_float;
...
} MyReceivingData;

Now, when we define these functions in the main program side, all we do is take the passed in parameters and fill a MySendingData structure with the values that need to be sent to the function. Also we fill in the message field with the name of the function that we are calling (using the enumerated type).

Finally we write this structure to the stream that we are using for IPC (pipe, socket, etc..) and then block on a read from the stream waiting to get back a MyReceivingData structure.

The other heavy weight process will be compiled with the real versions of these functions. That process just sits in a while loop, blocking on a read, waiting for a MySendingData typed block to appear in the stream. Then it does a switch on the data.message field to see what function was meant to be called. It then calls the message, with the parameters that are inside the sent data structure, fills a MyReceivingData structure with the return values and writes that across the IPC stream.

Of course there are some more details, but they are specific to the implementation. The basic idea was to be the simplest way to get past a shared library that wouldn't compile. This is not intended to be a long term way to do message passing over IPC, but works well given the application.