﻿<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/">
  <channel>
    <title>Yingle Jia's Weblog</title>
    <description>ACF, C++, C#, .NET</description>
    <link>http://www.wwwcoder.com/Weblogs/tabid/283/BlogId/126/Default.aspx</link>
    <language>en-US</language>
    <managingEditor>yljia@msn.com</managingEditor>
    <webMaster>webmaster@wwwcoder.com</webMaster>
    <pubDate>Sat, 17 May 2008 07:41:11 GMT</pubDate>
    <lastBuildDate>Sat, 17 May 2008 07:41:11 GMT</lastBuildDate>
    <docs>http://backend.userland.com/rss</docs>
    <generator>Blog RSS Generator Version 3.2.0.29758</generator>
    <item>
      <title>Design refactoring: delegates</title>
      <description>&lt;P&gt;&lt;STRONG&gt;What is delegate?&lt;BR&gt;&lt;/STRONG&gt;A delegate represents a callable entity. In the .NET world, a callable entity is either a static method or an instance method plus an object reference. In C++, function objects are also callable entities, e.g.:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;struct Foo {&lt;BR&gt;    void operator()() { ... }&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;Foo f;&lt;BR&gt;f(); // calls operator()&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Since function objects can contain state, they are much more useful than static functions. Thus a delegate class written for C++ must provide first class support for function objects.&lt;/P&gt;
&lt;P&gt;.NET also supports chaining delegates via Delegate.Combine and Delegate.Remove methods. Multicast delegates are commonly used for events.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The old design&lt;BR&gt;&lt;/STRONG&gt;In previous versions of ACF, the delegate design is just a simple porting from the .NET framework. Here is an example:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;static void F() { ... }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;RefPtr&lt;Delegate0&lt;void&gt;&lt;DELEGATE0&lt;VOID&gt; &gt; d = new Delegate0&lt;void&gt;&lt;VOID&gt;(&amp;F);&lt;BR&gt;d-&gt;Invoke();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The old design has the following drawbacks:&lt;BR&gt;- Performance. In the old design, delegates are reference types and are allocated on heap. This leads to significant performance overhead compared to C++ function pointers and function objects.&lt;BR&gt;- Syntax. The old syntax is a little hard to use. First, one has to remember and use Delegate0, Delegate1, Delegate2, ... instead of Delegate, and the function prototype is not quite clear (e.g. Delegate2&lt;void, int, float&gt;). Second, since delegates are reference types, one has to call the Invoke method to call the delegates, while the function call operator () is more nature for C++ developers.&lt;BR&gt;- Does not support function objects.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;The new design&lt;BR&gt;&lt;/STRONG&gt;The new design addresses all the problems listed above. The delegate class is now a concrete type like int, std::string, etc; it uses a new syntax based on template partial specialization (which is borrowed from boost.function); and it also supports function objects. Here are some examples:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;static void F() { ... }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;struct MyObj {&lt;BR&gt;    void G() { ... }&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;struct Functor {&lt;BR&gt;    void operator()(int n) { ... }&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;Delegate&lt;void ()&gt;&lt;VOID ()&gt; a(&amp;F);&lt;BR&gt;a();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;MyObj o;&lt;BR&gt;Delegate&lt;void ()&gt;&lt;VOID ()&gt; b(&amp;o, &amp;MyObj::G);&lt;BR&gt;b();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;Delegate&lt;void (int)&gt;&lt;VOID (int)&gt; c(Functor());&lt;BR&gt;c(10);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The delegate template uses the following declaration: Delegate&lt;R, (T1, T2, ..., TN)&gt;&lt;R TN) ..., T2, (T1,&gt;, where R is the return type, and T1, T2, ... TN are argument types. This syntax requires your compiler to support template partial specialization and function type parsing (I tried VC++ 7.1 and GCC 3.2). &lt;/P&gt;
&lt;P&gt;Here is the Delegate template class definition:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;template &lt;class TSignature&gt;&lt;CLASS TSignature&gt;&lt;BR&gt;class Delegate; // no body&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;template &lt;class R, class T1, class T2, ..., class TN&gt;&lt;CLASS class="" ..., T2, TN T1, R,&gt;&lt;BR&gt;template &lt;&gt;&lt;CLASS class="" ..., T2, TN T1, R,&gt;&lt;BR&gt;class Delegate&lt;R (T1, T2, ..., TN)&gt;&lt;R TN) ..., T2, (T1,&gt; {&lt;BR&gt;// Constructors/Destructor&lt;BR&gt;public:&lt;BR&gt;    Delegate();&lt;BR&gt;    Delegate(R (*fp)(T1, T2, ..., TN));&lt;BR&gt;    template &lt;class T&gt; &lt;CLASS T&gt;Delegate(T* obj, R (T::*mfp)(T1, T2, ..., TN));&lt;BR&gt;    template &lt;class TPtr, class T&gt; &lt;CLASS class="" T TPtr,&gt;Delegate(TPtr obj, R (T::*mfp)(T1, T2, ..., TN));&lt;BR&gt;    template &lt;class TFunctor&gt; &lt;CLASS TFunctor&gt;Delegate(const TFunctor&amp; f);&lt;BR&gt;    Delegate(const Delegate&amp; right);&lt;BR&gt;    ~Delegate();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;// Properties&lt;BR&gt;public:&lt;BR&gt;    bool IsEmpty() const;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;// Operators&lt;BR&gt;public:&lt;BR&gt;    Delegate&amp; operator=(const Delegate&amp; right);&lt;BR&gt;    operator bool() const;&lt;BR&gt;    bool operator!() const;&lt;BR&gt;    bool operator==(const Delegate&amp; right) const;&lt;BR&gt;    bool operator!=(const Delegate&amp; right) const;&lt;BR&gt;    R operator()(T1, T2, ..., TN) const;&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Comparing delegates&lt;BR&gt;&lt;/STRONG&gt;Delegate comparison is required when chaining delegates (more explicitly, removing delegates). The Delegate class supports comparison via the == and != operators. However, only static function and member function comparisons are supported, function object comparison is not supported. The reason why providing function object comparison is infeasible can be found in boost.function documents.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Chaining delegates&lt;BR&gt;&lt;/STRONG&gt;The new design supports chaining delegates through the DelegateList template class, which is a specialized singly linked list. It is also a function object, so you can use it to construct multicast delegates.&lt;/P&gt;
&lt;P&gt;Here is an examle:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;static void F() { ... }&lt;BR&gt;static void G() { ... }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;Delegate&lt;void ()&gt;&lt;VOID ()&gt; a(&amp;F), b(&amp;G);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;DelegateList&lt;&lt;DELEGATE&lt;VOID ()&gt;Delegate&lt;void ()&gt;&lt;VOID ()&gt; &gt; list;&lt;BR&gt;list += a;&lt;BR&gt;list += b;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;list(); // calls a() and b(), which calls F() and G()&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;Delegate&lt;void ()&gt;&lt;VOID ()&gt;&lt;VOID ()&gt; c(list); // c is a multicast delegate&lt;BR&gt;c(); // calls the delegate list&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Here is the DelegateList template class definition:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;template &lt;class TDelegate&gt;&lt;CLASS TDelegate&gt;&lt;BR&gt;class DelegateList; // no body&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;template &lt;class R, class T1, class T2, ..., class TN&gt;&lt;/FONT&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;&lt;CLASS class="" ..., T2, TN T1, R,&gt;&lt;BR&gt;template &lt;&gt;&lt;CLASS class="" ..., T2, TN T1, R,&gt;&lt;BR&gt;class DelegateList&lt;DELEGATE&lt;R TN) ..., T2, (T1,&gt; &lt;Delegate&lt;R (T1, T2, ..., TN)&gt; &gt; {&lt;BR&gt;// Constructors/Destructor&lt;BR&gt;public:&lt;BR&gt;    DelegateList();&lt;BR&gt;    DelegateList(const DelegateList&amp; right);&lt;BR&gt;    ~DelegateList();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;// Properties&lt;BR&gt;public:&lt;BR&gt;    bool IsEmpty() const;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;// Methods&lt;BR&gt;public:&lt;BR&gt;    void Add(const Delegate&lt;R (T1, T2, ..., TN)&gt;&amp; d);&lt;BR&gt;    void Remove(const Delegate&lt;R (T1, T2, ..., TN)&gt;&amp; d);&lt;BR&gt;    void Clear();&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New" color=#a52a2a&gt;// Operators&lt;BR&gt;public:&lt;BR&gt;    DelegateList&amp; operator=(const DelegateList&amp; right);&lt;BR&gt;    operator bool() const;&lt;BR&gt;    bool operator!() const;&lt;BR&gt;    void operator+=(const Delegate&lt;R (T1, T2, ..., TN)&gt;&amp; d);&lt;BR&gt;    void operator-=(const Delegate&lt;R (T1, T2, ..., TN)&gt;&amp; d);&lt;BR&gt;    R operator()(T1, T2, ..., TN) const;&lt;BR&gt;};&lt;/FONT&gt;&lt;FONT color=#a52a2a&gt;&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/875/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/875/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=875</guid>
      <pubDate>Tue, 01 Mar 2005 19:12:00 GMT</pubDate>
      <slash:comments>3</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=875</trackback:ping>
    </item>
    <item>
      <title>ACF Project Update</title>
      <description>&lt;P&gt;Hello readers, &lt;/P&gt;
&lt;P&gt;Recently I was a little busy and stopped blogging. Some readers mailed me asking whether I'll continue working on ACF or not. The answer is absolutely yes. However, I have to be very careful on future directions and certain technique issues before this framework is wide spread (I hope^_^). That's why I'm not going to emit many releases/documents before I spend enough time thinking and trying. Here are some thoughts on relation to the .NET framework and portability. Your feedback are always welcome.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Relation to the .NET framework&lt;BR&gt;&lt;/STRONG&gt;At the begining of this project, my initial thought was to bring the .NET framework to standard C++, so I tried hard to mimic nearly everything in the .NET framework, e.g. single inheritance, heap allocation, boxing/unboxing. However, practice proved this is not the right direction. People using C++/C# are developing very different kind of applications, a C++ framework has to be a thin wrapper around OS interfaces to give C++ developers performance and control, otherwise developers will resisit it (if they have choices). If you look at MFC (Microsoft Foundation Classes) or something similiar, you'll understand this situation. Of course, the .NET framework is well organized and designed, and is very easy to learn and use, we should take things that are suitable instead of reinventing ourselves. This leads to our decision on relation to the .NET framework: be close if suitable, otherwise make our own.&lt;BR&gt;Let's look at two examples.&lt;BR&gt;- Streams.&lt;BR&gt;We need to deal with various mediums (file, memory, network, etc), polymorphism is a good solution (we'll have a Stream abstract class and subclasses like FileStream, NetworkStream). Polymorphic objects are commonly allocated on heap (compared to concrete types, such as int, float), so an object management schema (such as reference counting) is necessary. To draw a conclusion, we could adopt the .NET framework stream design with minimum modifications.&lt;BR&gt;- Threading.&lt;BR&gt;The .NET framework threading model is fully based on Win32 threading model (which is not strange). The problem is that Win32 threading model is very complex and rich, whereas other platforms may only have minimum threading support. For example, pthread (POSIX Thread) does not have a general wait handle concept (Win32 supports waiting for single wait handle, as well as waiting for multiple wait handles). As a open source C++ framework, we're not going to provide a complex model that are not supported by many operating systems. Polymorphism and heap allocation are also not necessary here. So we will design our own threading model (may be close to boost.threads). For example, we may have the following mutex/lock model:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;class Mutex {&lt;BR&gt;public:&lt;BR&gt;    Mutex();&lt;BR&gt;    void Lock();&lt;BR&gt;    void Unlock();&lt;BR&gt;    ...&lt;BR&gt;}&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;class ScopedLock {&lt;BR&gt;public:&lt;BR&gt;    ScopedLock(Mutex&amp; m);&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;class Foo {&lt;BR&gt;    Mutex _m;&lt;BR&gt;    double _d;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    void Do() {&lt;BR&gt;        ScopedLock l(this-&gt;_m);&lt;BR&gt;        this-&gt;_d = sqrt(this-&gt;_d);&lt;BR&gt;    }&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;Portability&lt;BR&gt;&lt;/STRONG&gt;When I started this project, I worked only on Win32 and VC++. Portability was not considered at that time. After I published ACF, people asked for portability - as a open source project, portability of course should be a basic characteristic. And now I'm daily working on various platforms, so eventually this framework will be portable. I will talk about more about this later.&lt;/P&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/874/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/874/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=874</guid>
      <pubDate>Sun, 30 Jan 2005 18:37:00 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=874</trackback:ping>
    </item>
    <item>
      <title>Got a new job at IBM CSDL</title>
      <description>&lt;P&gt;Hello guys,&lt;/P&gt;
&lt;P&gt;Recently I got a new job (software engineer) at IBM China Software Development Lab (CSDL) located in Beijing, China. My job responsibility is development of IBM Workplace rich client (which I think is cool). I'll work on various platforms including Windows, Unix, Linux and MacOX, and use C++/Java. So I'll try to port ACF to other platforms in the future - isn't writing a portable C++ framework challenging and interesting? :-)&lt;/P&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/873/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/873/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=873</guid>
      <pubDate>Sun, 28 Nov 2004 00:39:00 GMT</pubDate>
      <slash:comments>8</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=873</trackback:ping>
    </item>
    <item>
      <title>Design Refactoring: type system</title>
      <description>&lt;P&gt;Since I published ACF, I got a lot of feedback from C++ guys. There are positive ones, such as:&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Nice job!...&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;...your framework looks pretty cool...&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;And also negative ones:&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;...single root inheritance, huge class tree, virtual functions everywhere... it looks like another OWL/MFC/VCL/AWT...&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;Great idea, but it is too simple and too hard to use...&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Well, I like feedback (including criticisms), since they tell you where you can improve. So recently I spent no time working on new features, but on correcting ACF (to make it more C++ smell and easy to use).&lt;/P&gt;
&lt;P&gt;In the past versions, I have been focusing on porting the .NET framework libraries to standard C++ (you see I tried to keep the classes, methods, etc. as close to the .NET ones as possible). However, this partly failed, because C++ and CLR are really very different models, simple porting will not work well (practice proved this).&lt;/P&gt;
&lt;P&gt;o CLR has an unified type system, all types inherit from the single root - System.Object. Reference types are allocated on heap and reclaimed by GC, which programmers cannot control. Value types are designed to improve performance, and there are built-in boxing/unboxing support.&lt;/P&gt;
&lt;P&gt;o C++ has the most flexible model, where classes are not required to inherit from some root class, and programmers can control where objects are allocated (static, stack, heap). When designing a C++ framework, we should always follow the C++ traditions (give the programmers performance and control), otherwise we will never succeed.&lt;/P&gt;
&lt;P&gt;This leads to the following considerations:&lt;/P&gt;
&lt;P&gt;o Separate concrete types and polymophic types. In C++, classes are usually categorized to concrete types, abstract types, nodes, etc (for detailed discussions please check &lt;EM&gt;The C++ Programming Language, Bjarne Stroustrup&lt;/EM&gt;).&lt;/P&gt;
&lt;P&gt;  - Concrete types are like C++ primitive types; they represent simple concepts (e.g. int, date, string, array) and have minimal dependency on other types; they are usually allocated on stack and pass by value or reference; they are not intended to be used as base classes.&lt;BR&gt;    Concrete types are much easier to use than other types in C++ (C++ creator Bjarne Stroustrup introduced operator overloading and reference (&amp;) to make them as close to C++ primitive types as possible). This is why some common classes, such as string or array, are implemented as concreate types in most C++ libraries (performance is another good reason). In previous versions of ACF, string and array are implemented as polymorphic types (they inherit from Acf::Object and thus have the VTBL) other than concrete types, this caused usability and performance problems for most cases. For example, people would like to see&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    class MyClass {&lt;BR&gt;        string get_Name();&lt;BR&gt;        void set_Name(const string&amp; value); // automatically handles const char* and const wchar_t*&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;        array&lt;String&gt; Split(const array&lt;wchar_t&gt;&amp; chars);&lt;BR&gt;    };&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;other than&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    class MyClass {&lt;BR&gt;        RefPtr&lt;String&gt; get_Name();&lt;BR&gt;        void set_Name(String* value); // cannot use const char* or const wchar_t*&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;        RefPtr&lt;Array&lt;String&gt; &gt; Split(Array&lt;wchar_t&gt;* chars);&lt;BR&gt;    };&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In the next version of ACF, string and array will be implemented as concrete types, which is a big breaking change (hope it paies). The good news is that you can use them as you would with std::string or std::vector (and a little easier), the bad news is that since they no longer inherit from Object, you have to call box(...) on them if you need to treat them as "objects" (in CLR, string and array do not need boxing/unboxing). Another little problem is naming convention: should I use String/Array&lt;T, R&gt;, or string/array&lt;T, R&gt;? (I guess most people will agree with the latter)&lt;/P&gt;
&lt;P&gt;There are also some other classes that will be implemented as concrete types other than reference types (e.g. StringBuilder, RegistryKey).&lt;/P&gt;
&lt;P&gt;- Polymophic types (include abstract types, nodes, etc) implement OO polymophism and form class hierarchy. For example, consider the encoding classes:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    class Encoding : public Object {&lt;BR&gt;        virtual int GetByteCount(const wchar_t* chars, int count) = 0;&lt;BR&gt;    };&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    class Utf8Encoding : public Encoding {&lt;BR&gt;        int GetByteCount(const wchar_t* chars, int count) {&lt;BR&gt;            ....&lt;BR&gt;        }&lt;BR&gt;    };&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;In ACF, polymophic types should inherit from Acf::Object, since it provides the following services:&lt;BR&gt;- Object life time management (reference counting)&lt;BR&gt;- Locking/unlocking&lt;BR&gt;- Detecting wether an object is allocated on heap or not (which is discussed in my previous posts)&lt;/P&gt;
&lt;P&gt;o The programmers can control how to allocate objects, include reference types. For example:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    // Allocate a FileStream object on stack&lt;BR&gt;    FileStream fs(...);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    // Use pointer since we don't know the real type of the input stream at compile time&lt;BR&gt;    class MyClass {&lt;BR&gt;        StreamPtr _stream;&lt;BR&gt;        MyClass(Stream* stream) : _stream(stream) { }&lt;BR&gt;    };&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/872/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/872/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=872</guid>
      <pubDate>Sun, 28 Nov 2004 00:09:00 GMT</pubDate>
      <slash:comments>1</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=872</trackback:ping>
    </item>
    <item>
      <title>ACF Portability</title>
      <description>Recently I spent some time playing with GCC 3.2 on Win32 (I used &lt;A href="http://www.bloodshed.net/dev"&gt;Dev-C++&lt;/A&gt; with &lt;A href="http://www.mingw.org"&gt;Mingw&lt;/A&gt; port). Now ACF compiles and runs OK, which is much easier than I thought (actually only a little code was modified) :-). The upcoming release of ACF will include Dev-C++ project files (well, I don't like make files though they are not hard to make) so you can build and use it with GCC on Win32.</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/871/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/871/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=871</guid>
      <pubDate>Tue, 09 Nov 2004 01:01:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=871</trackback:ping>
    </item>
    <item>
      <title>API consistency</title>
      <description>&lt;P&gt;The .NET team tried hard to make the .NET framework API consistent. They did a great job, however, there are still some design and naming inconsistency. The following items will be addressed in the next version of ACF.&lt;/P&gt;
&lt;P&gt;- Factory vs. Constructor for parsing&lt;BR&gt;Most classes in the BCL use the Parse pattern for parsing.&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;int i = int.Parse(“35”);&lt;BR&gt;DateTime d = DateTime.Parse(“10/10/1999”);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;However, the Guid structure does not follow this pattern:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;Guid g("1234567890123456789012");&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;Which shall be:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;Guid g = Guid.Parse("1234567890123456789012");&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;- Naming convention&lt;/P&gt;
&lt;P&gt;Just list a few:&lt;BR&gt;ASCIIEncoding =&gt; AcsiiEncoding&lt;BR&gt;UTF8Encoding =&gt; Utf8Encoding&lt;BR&gt;System.IO =&gt; System.Io&lt;BR&gt;...&lt;BR&gt;&lt;/P&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/870/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/870/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=870</guid>
      <pubDate>Sat, 06 Nov 2004 16:43:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=870</trackback:ping>
    </item>
    <item>
      <title>Design Refactoring: I/O</title>
      <description>&lt;P&gt;Recently I did some design refactoring to make ACF more C++ friendly (which means syntax, performance and control). This time let's take the Stream class as an example. In the .NET framework, the Stream class's main reading/writing methods are as follows:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;class &lt;STRONG&gt;Stream&lt;/STRONG&gt;&lt;BR&gt;{&lt;BR&gt;    abstract int &lt;STRONG&gt;Read&lt;/STRONG&gt;(byte[] buffer, int offset, int count);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    virtual int &lt;STRONG&gt;ReadByte&lt;/STRONG&gt;() {&lt;/FONT&gt;&lt;FONT face="Courier New"&gt;&lt;BR&gt;        byte[] buffer = new byte[1];&lt;BR&gt;        int n = Read(buffer, 0, 1);&lt;BR&gt;        return (n == 0 ? -1 : buffer[0]);&lt;BR&gt;    }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    abstract void &lt;STRONG&gt;Write&lt;/STRONG&gt;(byte[] buffer, int offset, int count);&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    virtual void &lt;STRONG&gt;WriteByte&lt;/STRONG&gt;(byte value) {&lt;BR&gt;        byte[] buffer = new byte[1] { value };&lt;BR&gt;        Write(buffer, 0, 1);&lt;BR&gt;    }&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;As you can see, the Stream class does not use unsafe code in order to be type-safe. However, the ReadByte/WriteByte methods have to be virtual and be overrided by subclasses, otherwise a temporary array will be created each time ReadByte or WriteByte is called. Another limitation is that you cannot directly read/write structures from/to streams (which is a frequently asked question for C++ developers who just start writing managed applications), which means you have to create temporary arrays in order to load/save structures.&lt;/P&gt;
&lt;P&gt;ACF is based on native C++ and thus does not have those limitations. Following is the current (new) design:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;class &lt;STRONG&gt;Stream&lt;/STRONG&gt; : public &lt;STRONG&gt;Object&lt;/STRONG&gt;&lt;BR&gt;{&lt;BR&gt;    virtual int &lt;STRONG&gt;Read&lt;/STRONG&gt;(byte* buffer, int count) = 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    int &lt;STRONG&gt;Read&lt;/STRONG&gt;(Array&lt;byte&gt;&lt;BYTE&gt;* buffer, int offset, int count) {&lt;BR&gt;        return Read(buffer-&gt;GetItemAddress(offset), count);&lt;BR&gt;    }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    int &lt;STRONG&gt;ReadByte&lt;/STRONG&gt;() {&lt;BR&gt;        byte b;&lt;BR&gt;        int n = Read(&amp;b, 1);&lt;BR&gt;        return (n == 0 ? -1 : b);&lt;BR&gt;    }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    virtual void &lt;STRONG&gt;Write&lt;/STRONG&gt;(byte* buffer, int count) = 0;&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    void &lt;STRONG&gt;Write&lt;/STRONG&gt;(Array&lt;byte&gt;&lt;BYTE&gt;* buffer, int offset, int count) {&lt;BR&gt;        Write(buffer-&gt;GetItemAddress(offset), count);&lt;BR&gt;    }&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;    void &lt;STRONG&gt;WriteByte&lt;/STRONG&gt;(byte value) {&lt;BR&gt;        Write(&amp;value, 1);&lt;BR&gt;    }&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;The ReadByte/WriteByte methods do not need to be virtual and be overrided, thanks to C++ memory model. Also now you can write structures directly to streams, as shown in the following code:&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;struct MyStruct {&lt;BR&gt;    int X;&lt;BR&gt;    double Y;&lt;BR&gt;};&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;MyStruct st = { 10, 3.14 };&lt;/FONT&gt;&lt;/P&gt;
&lt;P&gt;&lt;FONT face="Courier New"&gt;FileStreamPtr stream = File::Create(L"test.bin");&lt;BR&gt;stream-&gt;Write((const byte*)&amp;st, sizeof(st));&lt;BR&gt;&lt;/FONT&gt;&lt;/P&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/869/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/869/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=869</guid>
      <pubDate>Thu, 04 Nov 2004 00:41:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=869</trackback:ping>
    </item>
    <item>
      <title>On ACF 0.4 (Updated 8/13/2004)</title>
      <description>&lt;P&gt;Here are the items that I'm planning to add in ACF 0.4:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;DateTime parsing &amp; formatting 
&lt;LI&gt;Simple XML reading &amp; writing 
&lt;LI&gt;Threading update&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;The only problem is that I don't have enough time to work on them. These are quite a lot of work, and I, like you, have jobs to do. Some friends of mine told me that they would like to contribute if they have time - hope they could find some spare time. :-)&lt;/P&gt;
&lt;P&gt;Your feedback and suggestions are always welcome.&lt;/P&gt;
&lt;P&gt; &lt;/P&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/868/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/868/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=868</guid>
      <pubDate>Fri, 13 Aug 2004 13:30:00 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=868</trackback:ping>
    </item>
    <item>
      <title>An article worth reading: How Microsoft Lost the API War (Joel on Software)</title>
      <description>&lt;P class=slugText&gt;&lt;A href="http://www.joelonsoftware.com/articles/APIWar.html"&gt;How Microsoft Lost the API War&lt;/A&gt;. Though a little long. :-)&lt;/P&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/867/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/867/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=867</guid>
      <pubDate>Wed, 23 Jun 2004 17:16:00 GMT</pubDate>
      <slash:comments>0</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=867</trackback:ping>
    </item>
    <item>
      <title>What's new in ACF 0.3: base types parsing and formatting</title>
      <description>&lt;p&gt;&lt;font face="Verdana"&gt;Base types parsing and formatting are updated in ACF 
0.3. For example, the following code shows how to format integer using various 
formats:&lt;/font&gt;&lt;/p&gt;
&lt;pre style="font-name:Lucida Console; font-size:9pt; background-color:#e0e0e0"&gt;Int32 n = &lt;font color="#800000"&gt;123456789&lt;/font&gt;;
Console::WriteLine(n.ToString(&lt;font color="#FF0000"&gt;L"C"&lt;/font&gt;)); &lt;font color="#008000"&gt;// $123,456,789.00&lt;/font&gt;
Console::WriteLine(n.ToString(&lt;font color="#FF0000"&gt;L"E"&lt;/font&gt;)); &lt;font color="#008000"&gt;// 1.234568E+008&lt;/font&gt;
Console::WriteLine(n.ToString(&lt;font color="#FF0000"&gt;L"P"&lt;/font&gt;)); &lt;font color="#008000"&gt;// 12,345,678,900.00%&lt;/font&gt;
Console::WriteLine(n.ToString(&lt;font color="#FF0000"&gt;L"N"&lt;/font&gt;)); &lt;font color="#008000"&gt;// 123,456,789.00&lt;/font&gt;
Console::WriteLine(n.ToString(&lt;font color="#FF0000"&gt;L"F"&lt;/font&gt;)); &lt;font color="#008000"&gt;// 123456789.00&lt;/font&gt;
&lt;/pre&gt;
&lt;br&gt;
&lt;p&gt;&lt;font face="Verdana"&gt;The following function formats file sizes as shown in 
Windows Explorer (e.g. "3,012 KB"):&lt;/font&gt;&lt;/p&gt;
&lt;pre style="font-name:Lucida Console; font-size:9pt; background-color:#e0e0e0"&gt;StringPtr FormatFileSize(&lt;font color="#0000FF"&gt;int64&lt;/font&gt; size) {
    Int64 kb = size / &lt;font color="#800000"&gt;1024&lt;/font&gt;;
    &lt;font color="#0000FF"&gt;if&lt;/font&gt; (size % &lt;font color="#800000"&gt;1024&lt;/font&gt; != &lt;font color="#800000"&gt;0&lt;/font&gt;)
        kb++;
    &lt;font color="#0000FF"&gt;return&lt;/font&gt; kb.ToString(&lt;font color="#FF0000"&gt;L"N0"&lt;/font&gt;) + &lt;font color="#0000FF"&gt;str&lt;/font&gt;(&lt;font color="#FF0000"&gt;L" KB"&lt;/font&gt;);
}
&lt;/pre&gt;</description>
      <link>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/866/Default.aspx</link>
      <author>yljia@msn.com</author>
      <comments>http://www.wwwcoder.com/Weblogs/tabid/283/EntryID/866/Default.aspx#Comments</comments>
      <guid isPermaLink="true">http://www.wwwcoder.com/Default.aspx?tabid=283&amp;EntryID=866</guid>
      <pubDate>Sat, 19 Jun 2004 01:15:00 GMT</pubDate>
      <slash:comments>2</slash:comments>
      <trackback:ping>http://www.wwwcoder.com/DesktopModules/Blog/Trackback.aspx?id=866</trackback:ping>
    </item>
  </channel>
</rss>