2004年04月06日

——————————————————————————–
中学阶段

          10 PRINT “HELLO WORLD”
          20 END
——————————————————————————–
大学一年级

          program Hello(input, output)
            begin
              writeln(‘Hello World’)
            end.
——————————————————————————–
大学高年级

          (defun hello
            (print
              (cons ‘Hello (list ‘World))))
——————————————————————————–
初级程序员

          #include <stdio.h>
          void main(void)
          {
            char *message[] = {“Hello “, “World”};
            int i;

            for(i = 0; i < 2; ++i)
              printf(“%s”, message[i]);
            printf(“\n”);
          }
——————————————————————————–
编程老鸟

          #include <iostream.h>
          #include <string.h>

          class string
          {
          private:
            int size;
            char *ptr;

          public:
            string() : size(0), ptr(new char(‘\0′)) {}

            string(const string &s) : size(s.size)
            {
              ptr = new char[size + 1];
              strcpy(ptr, s.ptr);
            }

            ~string()
            {
              delete [] ptr;
            }

            friend ostream &operator <<(ostream &, const string &);
            string &operator=(const char *);
          };

          ostream &operator<<(ostream &stream, const string &s)
          {
            return(stream << s.ptr);
          }

          string &string::operator=(const char *chrs)
          {
            if (this != &chrs)
            {
              delete [] ptr;
             size = strlen(chrs);
              ptr = new char[size + 1];
              strcpy(ptr, chrs);
            }
            return(*this);
          }

          int main()
          {
            string str;

            str = “Hello World”;
            cout << str << end

            return(0);
          }
——————————————————————————–
编程高手

          [
          uuid(2573F8F4-CFEE-101A-9A9F-00AA00342820)
          ]
          library LHello
          {
              // bring in the master library
              importlib(“actimp.tlb”);
              importlib(“actexp.tlb”);

              // bring in my interfaces
              #include “pshlo.idl”

              [
              uuid(2573F8F5-CFEE-101A-9A9F-00AA00342820)
              ]
              cotype THello
           {
           interface IHello;
           interface IPersistFile;
           };
          };

          [
          exe,
          uuid(2573F890-CFEE-101A-9A9F-00AA00342820)
          ]
          module CHelloLib
          {

              // some code related header files
              importheader(<windows.h>);
              importheader(<ole2.h>);
              importheader(<except.hxx>);
              importheader(“pshlo.h”);
              importheader(“shlo.hxx”);
              importheader(“mycls.hxx”);

              // needed typelibs
              importlib(“actimp.tlb”);
              importlib(“actexp.tlb”);
              importlib(“thlo.tlb”);

              [
              uuid(2573F891-CFEE-101A-9A9F-00AA00342820),
              aggregatable
              ]
              coclass CHello
           {
           cotype THello;
           };
          };

          #include “ipfix.hxx”

          extern HANDLE hEvent;

          class CHello : public CHelloBase
          {
          public:
              IPFIX(CLSID_CHello);

              CHello(IUnknown *pUnk);
              ~CHello();

              HRESULT  __stdcall PrintSz(LPWSTR pwszString);

          private:
              static int cObjRef;
          };

          #include <windows.h>
          #include <ole2.h>
          #include <stdio.h>
          #include <stdlib.h>
          #include “thlo.h”
          #include “pshlo.h”
          #include “shlo.hxx”
          #include “mycls.hxx”

          int CHello::cObjRef = 0;

          CHello::CHello(IUnknown *pUnk) : CHelloBase(pUnk)
          {
              cObjRef++;
              return;
          }

          HRESULT  __stdcall  CHello::PrintSz(LPWSTR pwszString)
          {
              printf(“%ws\n”, pwszString);
              return(ResultFromScode(S_OK));
          }

          CHello::~CHello(void)
          {

          // when the object count goes to zero, stop the server
          cObjRef–;
          if( cObjRef == 0 )
              PulseEvent(hEvent);

          return;
          }

          #include <windows.h>
          #include <ole2.h>
          #include “pshlo.h”
          #include “shlo.hxx”
          #include “mycls.hxx”

          HANDLE hEvent;

           int _cdecl main(
          int argc,
          char * argv[]
          ) {
          ULONG ulRef;
          DWORD dwRegistration;
          CHelloCF *pCF = new CHelloCF();

          hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

          // Initialize the OLE libraries
          CoInitializeEx(NULL, COINIT_MULTITHREADED);

          CoRegisterClassObject(CLSID_CHello, pCF, CLSCTX_LOCAL_SERVER,
              REGCLS_MULTIPLEUSE, &dwRegistration);

          // wait on an event to stop
          WaitForSingleObject(hEvent, INFINITE);

          // revoke and release the class object
          CoRevokeClassObject(dwRegistration);
          ulRef = pCF->Release();

          // Tell OLE we are going away.
          CoUninitialize();

          return(0);
          }

          extern CLSID CLSID_CHello;
          extern UUID LIBID_CHelloLib;

          CLSID CLSID_CHello = { /* 2573F891-CFEE-101A-9A9F-00AA00342820 */
              0×2573F891,
              0xCFEE,
              0×101A,
              { 0×9A, 0×9F, 0×00, 0xAA, 0×00, 0×34, 0×28, 0×20 }
          };

          UUID LIBID_CHelloLib = { /* 2573F890-CFEE-101A-9A9F-00AA00342820 */
              0×2573F890,
              0xCFEE,
              0×101A,
              { 0×9A, 0×9F, 0×00, 0xAA, 0×00, 0×34, 0×28, 0×20 }
          };

          #include <windows.h>
          #include <ole2.h>
          #include <stdlib.h>
          #include <string.h>
          #include <stdio.h>
          #include “pshlo.h”
          #include “shlo.hxx”
          #include “clsid.h”

          int _cdecl main(
          int argc,
          char * argv[]
          ) {
          HRESULT  hRslt;
          IHello        *pHello;
          ULONG  ulCnt;
          IMoniker * pmk;
          WCHAR  wcsT[_MAX_PATH];
          WCHAR  wcsPath[2 * _MAX_PATH];

          // get object path
          wcsPath[0] = ‘\0′;
          wcsT[0] = ‘\0′;
          if( argc > 1) {
              mbstowcs(wcsPath, argv[1], strlen(argv[1]) + 1);
              wcsupr(wcsPath);
              }
          else {
              fprintf(stderr, “Object path must be specified\n”);
              return(1);
              }

          // get print string
          if(argc > 2)
              mbstowcs(wcsT, argv[2], strlen(argv[2]) + 1);
          else
              wcscpy(wcsT, L”Hello World”);

          printf(“Linking to object %ws\n”, wcsPath);
          printf(“Text String %ws\n”, wcsT);

          // Initialize the OLE libraries
          hRslt = CoInitializeEx(NULL, COINIT_MULTITHREADED);

          if(SUCCEEDED(hRslt)) {

              hRslt = CreateFileMoniker(wcsPath, &pmk);
              if(SUCCEEDED(hRslt))
           hRslt = BindMoniker(pmk, 0, IID_IHello, (void **)&pHello);

              if(SUCCEEDED(hRslt)) {

           // print a string out
           pHello->PrintSz(wcsT);

           Sleep(2000);
           ulCnt = pHello->Release();
           }
              else
           printf(“Failure to connect, status: %lx”, hRslt);

              // Tell OLE we are going away.
              CoUninitialize();
              }

          return(0);
          }
——————————————————————————–
黑客初阶

          #!/usr/local/bin/perl
          $msg=”Hello, world.\n”;
          if ($#ARGV >= 0) {
            while(defined($arg=shift(@ARGV))) {
              $outfilename = $arg;
              open(FILE, “>” . $outfilename) || die “Can’t write $arg: $!\n”;
              print (FILE $msg);
              close(FILE) || die “Can’t close $arg: $!\n”;
            }
          } else {
            print ($msg);
          }
          1;
——————————————————————————–
黑客有成

          #include <stdio.h>
          #define S “Hello, World\n”
          main(){exit(printf(S) == strlen(S) ? 0 : 1);}
——————————————————————————–
黑客高手

          % cc -o a.out ~/src/misc/hw/hw.c
          % a.out
——————————————————————————–
黑客大虾

          % cat
          Hello, world.
          ^D
——————————————————————————–
初级经理

          10 PRINT “HELLO WORLD”
          20 END
——————————————————————————–
中级经理

          mail -s “Hello, world.” bob@b12
          Bob, could you please write me a program that prints “Hello, world.”?
          I need it by tomorrow.
          ^D
——————————————————————————–
高级经理

          % zmail jim
          I need a “Hello, world.” program by this afternoon.
——————————————————————————–
首席执行官

          % letter
          letter: Command not found.
          % mail
          To: ^X ^F ^C
          % help mail
          help: Command not found.
          % damn!
          !: Event unrecognized
          % logout
——————————————————————————–

2004年04月04日

IUnknown


IDL描述:
interface IUnknown
{
  HRESULT QueryInterface([in]REFIID iid, [out]void** ppv);
  ULONG AddRef(void);
  ULONG Release(void);
}


构造函数、AddRef、Release的某种实现可能
class CUnknown : public IUnknown
{
public:
  CUnknown();
  ~CUnknown();
  virtual HRESULT QueryInterface(const IID& iid, void** ppv);
  virtual ULONG AddRef();
  virtual ULONG Release();
private:
  int m_Ref;
};
CUnknown::CUnknown()
{
  m_Ref = 0;
  // 其它的初始化工作
}
ULONG CUnknown::AddRef()
{
  m_Ref++;
  return (ULONG)m_Ref;
}
ULONG CUnknown::Release()
{
  m_Ref–;
  if (m_Ref == 0)
  {
    delete this;
    return 0;
  }
  return (ULONG)m_Ref;
}


接口查询
QueryInterface可用于获得对象所支持的任何一个接口指针。
HRESULT QueryInterface([in]REFIID iid, [out]void** ppv);
iid为查询接口的IID,ppv用来保存查询得到的接口指针。


返回值:
S_OK:查询成功完成。
E_NOINTERFACE:对象不支持要查询的接口。
E_UNEXPECTED:意外错误。


查询原则:
1、对于同一个对象的不同接口指针,查询得到的IUnknown接口必须完全相同。
2、对一个接口查询自身必须是成功的。
3、从第一个接口查询到第二个接口,则从第二个接口查询第一个接口应成功。
4、从第一个接口查询到第二个接口,从第二个接口查询到第三个接口,则一定能从第三个接口查询到第一个接口。
5、查询借口成功与否应该与时间无关。


QueryInterface的某种实现
HRESULT CMyObject::QueryInterface(const IID& iid, void** ppv)
{
  if (iid == IID_IUnknown)
  {
    *ppv = (IMyInterface *)this;
   ((IMyInterface *)(*ppv))->AddRef();
  }
  else if (iid == IID_IMyInterface)
  {
    *ppv = (IMyInterface *)this;
    ((IMyInterface *)(*ppv))->AddRef();
  }
  else if (iid == IID_Another)
  {
    *ppv = (IAnother *)this;
    ((IAnother *)(*ppv))->AddRef();
  }
  else
  {
    *ppv = NULL;
    return E_NOINTERFACE;
  }
  return S_OK;
}

2004年04月03日

MSDN的中文化,对中国的程序员来说无疑是一件好事。



接触过很多程序员——包括我自己——一致认为英文是编程的一道门槛。不懂英文则看不懂最新的技术,而懂英文的高手则没有时间去把这些东西译成中文。
一年多以来我都是一边看着英文资料,一边用金山词霸相助,咬牙地啃过一篇篇文章。对于翻译,我也只是关注经典的,翻译经典的。
扯远了,不过MSDN的中文化终归是一件大好事。

2004年04月01日

接口描述语言IDL
它可以用于定义COM接口,也可以描述自定义的数据结构。对于接口成员函数,可以指定每个参数的类型、输入输出特性,甚至可以支持可变长度数组的描述。例如:
interface IMyInterface
{
  HRESULT func1();
  HRESULT func2([in]string);
  HRESULT func3([in]string, [out]string*);
};
VC中提供的工具MIDL可以将IDL接口描述文件(*.idl)编译成C/C++兼容的接口描述头文件(*.h)。


 


接口的内存模型
以IMyInterface为例,它的C++实现如下:
class IMyInterface
{
  virtual HRESULT func1() = 0;
  virtual HRESULT func2(string) = 0;
  virtual HRESULT func3(string, string*) = 0;
};
相应的COM对象实现则为:
class CMyObject : public IMyInterface
{
public:
  CMyObject();
  ~CMyObject();
  virtual HRESULT func1();
  virtual HRESULT func2(string);
  virtual HRESULT func3(string, string*);
private:
  // 其它的成员
};
此外,还需要实现一个创建COM对象实例的函数以将IMyInterface的接口指针和一个指向CMyObject对象的指针关联起来。这样在调用了该函数对接口指针初始化之后,就可以利用C++继承和多态的特性用借口来访问和操作这个COM对象了。