| 为C++脚本加入新的函数、数据类型等元素编写脚本程序当然要提供一些东西给脚本调用,和前面一样,还是直接看例子比较好(主要是文采不好&&比较懒~~)。 在这个例子里,我们给C++脚本加入一个创建Windows窗口功能。 假设我们有一个CWin类,可以创建Windows窗体,它有setBound和setTitle方法,用于设定位置大小和标题。另外还有一个CMsgLoop类负责消息循环。
 先放上它们的代码(这个代码不必深究,现在我们关心的不是怎样显示窗体,而是怎样把CWin类嵌入到脚本里去): 
     #include <windows.h> class CWin{ private:     static int gm_count;      HWND m_hWnd;     static void RegisterWindow();      void Clear();     static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); public:     CWin(const CWin* parent);      ~CWin();     void setBound(int x, int y, int width, int height);     void setTitle(const char* title); };   class CMsgLoop{ private:     MSG m_msg; public:     int run(); };  
     #include "addin.h" int CWin::gm_count = 0; CWin::CWin(const CWin* parent) {     DWORD dwStyle = WS_VISIBLE;     HWND hWndParent = NULL;          if(parent == NULL)     {         dwStyle |= WS_OVERLAPPEDWINDOW;     }     else     {         dwStyle |= WS_CHILD;         hWndParent = parent->m_hWnd;     }       RegisterWindow();     m_hWnd = CreateWindow(         "CInt.CWin",         NULL,         dwStyle,         0,0,100,100,         hWndParent,         0,0,0);          if(m_hWnd){         gm_count++;         ::SetProp(m_hWnd, "CWin", this);     } }   CWin::~CWin() {     Clear(); }   void CWin::Clear() {     if(m_hWnd){         ::RemoveProp(m_hWnd, "CWin");         ::DestroyWindow(m_hWnd);         if(--gm_count<=0) ::PostQuitMessage(0);     } }   void CWin::RegisterWindow() {     static bool fRegistered = false;     if(!fRegistered)     {         WNDCLASS wc={             0,WndProc,             0,0,             ::GetModuleHandle(NULL),             NULL,LoadCursor(NULL, IDC_ARROW),             (HBRUSH)(COLOR_BTNFACE+1),             0,"CInt.CWin"         };         if(::RegisterClass(&wc) != 0)             fRegistered = true;     } } LRESULT CALLBACK CWin::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {     if(uMsg == WM_DESTROY)     {         CWin *pWin = (CWin*)::GetProp(hwnd, "CWin");         if(pWin)pWin->Clear();     }     else if(uMsg == WM_PAINT)     {         RECT rc;         ::GetClientRect(hwnd, &rc);                  PAINTSTRUCT ps;         HDC hdc = ::BeginPaint(hwnd, &ps);         char text[100];         ::GetWindowText(hwnd, text, 100);         ::DrawText(hdc, text, -1, &rc, DT_CENTER|DT_SINGLELINE|DT_VCENTER);         ::DrawEdge(hdc, &rc, BDR_RAISEDINNER,BF_RECT);         ::EndPaint(hwnd, &ps);     }     return ::DefWindowProc(hwnd,uMsg,wParam,lParam); }   void CWin::setBound(int x, int y, int width, int height) {     if(m_hWnd)     {         ::MoveWindow(m_hWnd,x,y,width,height,TRUE);     } }   void CWin::setTitle(const char *title) {     if(m_hWnd)     {         ::SetWindowText(m_hWnd, title);     } }   int CMsgLoop::run() {     while(::GetMessage(&m_msg,NULL,0,0))     {         TranslateMessage(&m_msg);         DispatchMessage(&m_msg);     }     return (int)m_msg.wParam; }  在程序里,我们可以这样使用它: 
    #include "addin.h"   int main(int argc, char* argv[]) {     CWin frame(NULL);      frame.setBound(100,100,300,200);     frame.setTitle("hello");       CWin child(&frame);      child.setBound(5,5,60,25);     child.setTitle("child1");       CWin child2(&frame);      child2.setBound(5,40,60,25);     child2.setTitle("child2");       CWin frame2(NULL);        CMsgLoop ml;        return ml.run(); }  不过现在的目的可不是让它在我们的程序里执行,而是作为脚本给Cint来执行。现在开始吧: 新建一个addin_script.h文件,输入CWin和CMsgLoop的公共成员: 
    #ifndef __CINT__     #include "addin.h" #else     class CWin{     public:         CWin(const CWin* parent);         ~CWin();         void setBound(int x, int y, int width, int height);         void setTitle(const char* title);     };     class CMsgLoop{     public:         int run();     };     #endif  完成后在命令行执行: cint -c-1 addin_script.h 这时会生成G__cpplink.C和G__cpplink.h两个文件,这两个文件是我们的程序和脚本之间的桥梁。把这两个文件以及前面的addin.cpp加入到我们的项目中,注意要设置G__cpplink.C成"编译为C++代码"(或者干脆扩展名改成.cpp),
 否则不能通过编译。
 我们主程序的代码为: 
    #include "G__cpplink.h" int main(int argc, char* argv[]) {     G__init_cint("cint");     G__cpp_setup();      G__loadfile("script.cxx");     G__calc("main()");     G__scratch_all();     return 0; }  C++脚本代码script.cxx为(和我们的主程序放一起): int main(int argc, char* argv[])
{
    CWin frame(NULL); 
    frame.setBound(100,100,300,200);
    frame.setTitle("hello");
    CWin child(&frame); 
    child.setBound(5,5,60,25);
    child.setTitle("child1");
    CWin child2(&frame); 
    child2.setBound(5,40,60,25);
    child2.setTitle("child2");
    CWin frame2(NULL); 
    CMsgLoop ml; 
    return ml.run();
}
你可以试着修改script.cxx看看效果。总结一下上面的步骤:
 首先,编写好你要嵌入脚本的类、函数或类型定义等东东 然后,把公开给脚本的部分(如类的public部分、指定的类型定义等)重新声明一下保存为新的头文件。 再然后用“cint -c-1 头文件”或"cint -c-2 头文件"(分别对应C++和C代码)生成脚本嵌入函数。用cint读取头文件时会带有__CINT__宏定义,我们可以利用这个特性把脚本用的声明和程序用的声明放到
 一个文件里(就象这个例子里做的一样)
最后,调用嵌入函数G__cpp_setup()或G__c_setup()把这我们写好的东东嵌入到脚本中供脚本使用。 
 |