Monday, October 3, 2011

Classes and DLLs

DLLs are libraries with named functions in them. Usually the names are human readable. C++ has this thing in it call named mangling.  This is to allow for overloaded functions and other things.  When you build a C++ DLL, all the functions will be exported as their mangled names.  Every compiler mangles differently.  This isn't a problem if you use the LIB file, because the compiler will automatically link to the correct mangled name in the DLL.  This requires that you be statically linked to the DLL, and that it be compiled with the same compiler.  If you want to load DLLs at runtime using LoadLibrary, you will need to know the mangled name for use with GetProcAddress.  So all this gets complicated really fast.

There is a simple way around this using a factory method.  Take for example DirectX.   You call Direct3DCreate9 to get pointer to a IDirect3D9 object.  Instead of calling "new Direct3D9()", you call the factory method.  Instead of calling "delete obj" you call Release.

To do this, you have to follow a few rules.   You must use the factory method to create, and use the release method delete.  This is to keep the memory allocator happy.

You can expand on the factory method by passing in an argument to select the type of object to return.
MyObject* obj = (MyObject*) CreateObject( MY_OBJECT_TYPE );

CreateObject figgures out the correct object to create/return based on the supplied argument.  The supplied argument could be an enum if you are returning a fix number of known object types.   You could alternatively pass in a string to match against and build a look up table to match against.

hmod = LoadLibrary("some.dll");
Fn CreateObject = (void* (*(char*)) )GetProcAddress( hmod, "CreateObject");
CreateObject("MyObject);

Monday, September 26, 2011

New DVR

Ordered a Centon Infinitv. For those who don't know, its a PCIe card for your computer that allows you to record up to 4 digital (HD) cable channels. So now I can set up to 4 shows to DVR at once. Only needed to run the setup and restart the computer. Windows Media Center picked it up right away as 4 tuners. The longest part was waiting for all the channels to be found.

One feature that is really cool is being able to use the extra tuners on other PC's on the network. Ceton refers to this as 'network tuners'. Requires you to install software on both computers and to have a fairly fast network. I tried it over 54mb wireless. The software warns against this but I tried anyways. It worked, but saturated my wireless. Using a full 100mbit or gigabit would probably work just fine.

The only problem with digital cable is you need a M-Card from the cable company. This requires a service tech to come out to install/activate one. As far as I can tell, they are required to come out because you aren't guaranteeing a card will work the first time. I still need to schedule that, since summer seems to be the busiest time, its hard to get one to come out

Friday, August 26, 2011

"Shims" in C++/CLI

I saw this post about writing a plugin DLL for the Optimus Mini Three. The DLL needs to be written in C++ but what if you wanted to write it in .NET (ie C#). C# doesnt allow you to directly write normal DLLs that C++ can call into. Instead you need what is called a "shim". A little piece of glue code.

Here is some example glue code to create a plugin for the Mini Three

#define WIN32_LEAN_AND_MEAN  
#include "windows.h"  
#include "OptPlugin.h" 
 #include <vcclr.h>
template<typename T>
 class Shim : public OptimusMiniPlugin {
 	gcroot obj; 
public: 	
Shim(int f) { obj = gcnew T(f);	}
virtual BOOL __stdcall Paint(HDC hdc){ return obj->Paint( IntPtr(hdc) );} 
virtual void __stdcall OnKeyDown(){ obj->OnKeyDown();} 
virtual LPARAM __stdcall GetInfo(int index) { 
#ifdef _WIN64
  return obj->GetInfo(index).ToInt64();
#else
  return obj->GetInfo(index).ToInt32();
#endif
  } 
};   
PLUGIN_EXPORT(Shim)

"Shim" is a C++ class while SomeDotNetClass is a managed class. PLUGIN_EXPORT is the provided macro from Optimus to create the plugin exports. The key to this is the gcroot. It allows you to reference a managed object from the non-managed class. You then just forward call your calls to the managed class. Create your managed class in a C# assembly and reference it from the C++ dll.

Thursday, August 25, 2011

Macros in C#

Macros are a wonder feature found in C++. It allows you to write a template of sorts and use throughout. I bet you didn't know C# allows for templates too.

There is a wonderful template library built in to visual studio called T4. Just add a new file to your project and change the extension to ".tt"



<#@ template language="C#" #>
// This code was generated by a tool.
// Any changes made manually will be lost
// the next time this code is regenerated.
using System;

public class <#= this.ClassName #>
{
 public static void SayHello()
 {
 Console.WriteLine(”Hello World”);
 }
}
<#+
string ClassName = "MyClass";
#>

When you compile this will make a ".cs" file of the same name automatically. These templates are much more powerful than C macros. You have full access to any assemblies in the GAC (for example XML, Networking, and IO).

Tuesday, March 15, 2011

Realtime translation with jquery

For those who might be trying to follow the news in japan on ustream, you might notice all the comments are in Japanese. Here is some javascript to translate real time


var head= document.getElementsByTagName('head')[0];
var script= document.createElement('script');
script.type= 'text/javascript';
script.src= 'http://code.jquery.com/jquery-1.5.1.min.js';
head.appendChild(script);

var script2= document.createElement('script');
script2.type= 'text/javascript';
script2.src= 'http://jquery-translate.googlecode.com/files/jquery.translate-1.4.7-debug-all.js';
head.appendChild(script2);

tr = function(){
$('iframe').contents().find('*[data-template="ssMessageItem"]').translate('jp','en');
setTimeout("tr()", 100);
}
tr();




If you care what it does. It loads up jQuery, then loads up a jQuery plugin to do google translation. Sets up a timer to translate all the elements that look like messages '*[data-template="ssMessageItem"]' from jp to en.

Saturday, February 19, 2011

down casting unknown types

In C++ you have classes. Classes are objects that can be based off of other classes. Casting between class types is usually done by.

Foo* f = new Foo()
Bar *b = (Bar*)f;

The problem with this is its not safe. If Bar is not a base class of Foo then b is invalid and will do who knows what. There is a second possible problem too. If Foo has multiple base classes, say Bar and Baz, the cast might not work either. This depends on how the class was declared

class Foo : public Bar, public Baz

or

class Foo : public Baz, public Bar

If it was the first one, the code would have been okay. If it was the second then we just tried to cast a pointer to Baz into a pointer to Bar, which isn't okay. Casting to a base type is called down casting. How do you safely cast into Bar?

Welcome our good friend dynamic_cast. dynamic_cast knows how the classes were declared and will correct cast for you. It'll shift pointers around and return the right thing. And in case you tried to cast to something that is impossible, it returns a null. The one thing dynamic_cast wont do is cast from a void*. This is known as up casting, or casting from a base class to a derived class.

void* v = new Foo();
Bar* b = (Bar*)new Foo();
Foo* x = dynamic_cast(v); // returns null
Foo* y = dynamic_cast(b); // returns Foo*

There is no path to Bar from void, so dynamic_cast wont work here. Using void* as a generic pointer is pretty common, but unfortunately you can't dynamic_cast from it. What you need to do is create a common base class for everything to share. Lets call it Object

class Object{};

class Bar : public Object
{ };
class Baz : public Object
{ };
class Foo : public Bar, public Baz
{};

Now everything shares a common base class called Object. The problem is Foo has 2 Object base classes, one for Bar and one for Baz. If you drew out the memory, it might look something like this.

Foo
+-----
|Object
|Bar
+-----
+-----
| Object
| Baz
+-----

Now, if you tried to cast Foo to Object, which Object should it point to, the one in Bar or the one in Baz. Using a normal (Object*)new Foo() would get you the Object from bar. Using dynamic_cast would result in a compile warning of C4540 (dynamic_cast used to convert to inaccessible or ambiguous base) and it would return null. You can fix this by using a virtual base class.


class Object{};

class Bar : virtual public Object
{ };
class Baz : virtual public Object
{ };
class Foo : public Bar, public Baz
{};

Notice the "virtual public Object". This tells the compiler to only make one Object for Foo, and have Bar and Baz share it. Now dynamic_cast will be able to cast from Object to Foo and vise-versa. Now you can use Object* instead of void* as your generic pointer. This will allow you to dynamic_cast up and down all you want. The one thing you can't use this for is for primitives like int, char, float. But you can't derive anything from that anyway so it shouldn't matter.

One idea, you can use these for a Service Registry. Just make all your services have a virtual base class of IService.

class ServiceRegistry
{
public:
void Add(char* name, IService *i);
IService Find(char* name);
}

// cast to IService to add
reg->Add("my_service", dynamic_cast(my_service) );
// cast from IService to get
MyService* find = dynamic_cast( reg->Find("my_service") );


Thursday, February 3, 2011

Zombies from Microsoft

Apparently there is a bug in windows that causes Zombie Console windows.


Whats a zombie window? Its a window with no process. Every window should have a process associated with it. When that process closes, so should its window. But if the process closes some how without ever closing the window, it turns into a Zombie window.

Zombie windows are bad because they can't be closed and they prevent you from shutting down, and logging out of windows. Windows gets stuck trying to close them.

I have never seen a solution on how to get rid of them, so I came up with my own. I call it Zombie Killer.

What it does is list all your windows and lets you select one to close. You just need to double click the window in the list and it will be handled.