Feeds:
Posts
Comments

Posts Tagged ‘C++’

I am learning iOS programming. After some research, I’ve basically decided to write my apps in Objective C++: writing my models (the M in MVC pattern) in pure C++ as long as possible and writing the UI in Objective C++. This is partially because I have C++ programming background and C++0x makes C++ programming more fun, and partially because it would be easier for me to port the models to other platform.

I will probably use NSString to handle strings, as I need to support Unicode and wchar_t in iOS is 4 bytes, which might make it less-efficient to convert between NSString and std::wstring.

I will write the models as static libraries using separate Xcode projects.

Advertisements

Read Full Post »

It is not always possible to rewrite your C or C++ legacy applications in .NET languages in one shot. Sometimes you have to do it module by module, step by step. In other words, you may have to use unmanaged DLLs in your .NET applications.Suppose you want to an unmanaged DLL, name Foo.dll, in your C# applications. What approach would your choose?

If you only want to use a small number of C functions expose by the DLL and the parameters can be marshalled across the managed and unmanaged boundary, you could use P/Invoke.

If you want to use a large number of the functions exposed by the DLL, and/or the some function parameters are hard to map to C# structs, or if the DLL exposes C++ interfaces or C++ classes, you will have to create another layer using C++/CLI as the bridge between the managed application and the unmanaged DLL. The bridge layer would be a DLL that expose .NET classes that you can use in the .NET application. The .NET classes normally delegate the real jobs to the unmanaged DLL.

The approach works great until you want to replace the Foo.dll with a purely managed DLL. The new managed DLL must provide exactly the same classes of the C++/CLI bridge, otherwise, you will have to modify the managed application. Even if you provide the same classes in the managed DLL, you still have to recompile the .NET application. This is all because the .NET application and the bridge are tightly coupled.

I would propose another approach, illustrated in the following component diagram. Foo.Contract.dll defines the interface that the bridge should implement. Foo.Bridge.dll implements the interface by delegating the real jobs to Foo.dll. There is no link-time dependency between the .NET application and Foo.Bridge.dll. The .NET application will load Foo.Bridge.dll at runtime.

Foo.Contract.dll should only defines interfaces, enums, structs, exception classes, and sealed classes if necessary. We should define the interfaces as if we are designing a reusable API, focusing on how to make it easier for the clients to use, rather than how to make it easy to be implemented. Ideally, the contract should define a rich domain model to make it easier to understand and evolve. And there should be a façade interface (or a factory interface), acting as the entry point into the domain model.

Foo.Bridge.dll implements the interfaced defined in Foo.Contract.dll by delegating to Foo.dll.

As mentioned earlier, the .NET application doesn’t link to Foo.Bridge.dll directly, instead it loads the DLL at runtime. All it needs to know are the DLL name and the name of the class that implements the façade interface. We could add an entry in the appSettings section of the configuration file. For example:

<configuration>
  <appSettings>
    <add  key="Foo.IFacade" value="Foo.Bridge.dll,  FacadeImpl"  />
  </appSettings>
</configuration>

The key is the façade interface name. The value contains the DLL name and the class name. At runtime, the .NET application loads the DLL, finds the Type object representing  the Façade class, and calls the Activator.CreateInstance() method to create an instance of the class and casts to Foo.IFacade. From then on, you can use all functionality defined in Foo.Contract.dll.

If, in future, we want to replace Foo.dll with a pure .NET DLL, say, Foo.Managed.dll (that implements the interfaces defined in Foo.Contract.dll), we can simply modify the setting to

<add  key="Foo.IFacade" value="Foo.Managed.dll,  FooFacade"  />

And the application should just work without re-complication.

This approach allows us to replace unmanaged DLLs with managed DLLs without having to modify or even recompile the application, thus achieving “close to modification and open to extension” (the open-closed principle). And it forces us to design a sound API, which also makes the bridge unit-testable.

Read Full Post »

The Problem

Suppose you need to use a legacy C++ class designed in COM style. Some methods of the class return HRESULT, and take a pointer as a parameter that could point to an int, a short, a std::string, an enum, and so on. For example:

HRESULT GetName(std::string* name);

Solution 1

The most obvious way of calling this method is:

std::string name;
if (SUCCEEDED(obj->GetName(&name)))
    m_name = name;
else
    m_name = "Untitled";

If you call the methods over and over again using this way, you will create quite a bit of duplicated code.

Solution 2

One way to solve this is to provide a helper function for the methods that have the same parameter type. For example, for the methods that take int* as the parameter, you could write a helper function, something like follows:

int GetInt(MyClass* obj, HRESULT (MyClass::*func)(int*), int defaultValue)
{
    int i = defaultValue;

    if (SUCCEEDED(obj->*func(&i))) // call the member method
        return i;
    else
        return defaultValue;
}

The obj parameter points to a MyClass object on which the member method is to be called; the func parameter points to a member method of MyClass to be called; the defaultValue parameter is to be returned if the function call to the member method fails. The helper function hides the details of checking the HRESULT returned from the member method.

You can now use the helper function when you need to call a method on a MyClass object, e.g.:

int length = GetInt(obj, &MyClass::GetLength, 0);

The code for calling the GetName() method can be reduced to:

m_name = GetString(obj, &MyClass::GetName, "Untitled");

The code becomes much more concise. However, there is a problem: you need to write a helper function for each group of methods of each class, where each group of methods has the same parameter type. Let’s say, you have five classes and all of them have methods that use 10 different parameter types, then you have to create 50 helper functions, which is quite a bit of (seemingly duplicated) code.

A Better Solution

Is there a better solution? Yes, by using a combination of template and member function pointers. We can define a template Functor class PropertyGetter:

///////////////////////////////////////////////////////////////////////////////
// A Functor for calling member methods that returns HRESULT and takes a
// pointer as the parameter, e.g. HRESULT MyClass::GetLength(int* length)
//
// T represents a class whose method is to be called.
// ARG represents the type of the parameter of the method to be called.
///////////////////////////////////////////////////////////////////////////////
template<typename T, typename ARG>
class PropertyGetter
{
    T* m_object; // The object on which the method is to be called
    HRESULT (T::*m_func)(ARG*); // The member method to be called

public:
    PropertyGetter(T* obj, HRESULT (T::*func)(ARG*))
      : m_object(obj), m_func(func)
    {
    }

    ARG operator()(ARG defaultValue)
    {
        ARG a = defaultValue;
        if (SUCCEEDED((m_object->*m_func)(&a))) // call the member method
        {
            return a;
        }
        else
        {
            return defaultValue;
        }
    }
};

The template parameter T represents a class whose methods you want to call, and ARG represents the type of the parameter of a method. The constructor takes two parameters: a pointer to a class instance and a pointer to a member method. The operator() calls the target method on the class instance. If the call succeeds, it returns the value returned from the method; otherwise, it returns the defaultValue passed in.

With this template class, you can call any method of any class, as long as the method returns HRESULT and takes a pointer as the parameter. The GetName() and GetLength() methods can now be called as:

m_name = PropertyGetter<MyClass, std::string>(obj,
    &MyClass::GetName)("Untitled");

int length = PropertyGetter<MyClass, int>(obj, &amp;MyClass::GetLength)(0);

which can be conceptually translated into:

{
    PropertyGetter<MyClass, std::string> temp1(obj, &aMyClass::GetName);
    m_name = temp1("Untitled");
}

int length;
{
    PropertyGetter<MyClass, int> temp2(obj, &MyClass:GetLength);
    length = temp2(0);
}

As you can see in this example, when used properly, the combination of template and function pointers can help you make your code more concise.

Read Full Post »