为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()把这我们写好的东东嵌入到脚本中供脚本使用。
|