夜鹰教程网-程序员的加油站
 当前位置:文章中心 >> Python
为C++脚本加入新元素
夜鹰教程网 来源:www.yyjcw.com 日期:2016-11-16 15:02:25
本文介绍了怎样用Cint解析C++脚本,以及怎样简单地把自定义类嵌入到脚本中去。

为C++脚本加入新的函数、数据类型等元素

编写脚本程序当然要提供一些东西给脚本调用,和前面一样,还是直接看例子比较好(主要是文采不好&&比较懒~~)。

在这个例子里,我们给C++脚本加入一个创建Windows窗口功能。

假设我们有一个CWin类,可以创建Windows窗体,它有setBound和setTitle方法,用于设定位置大小和标题。
另外还有一个CMsgLoop类负责消息循环。

先放上它们的代码(这个代码不必深究,现在我们关心的不是怎样显示窗体,而是怎样把CWin类嵌入到脚本里去):

  1. // addin.h文件
  2. #include <windows.h>
  3. class CWin{
  4. private:
  5.     static int gm_count; //CWin总数,最后一个CWin负责退出消息循环
  6.     HWND m_hWnd;
  7.     static void RegisterWindow(); //注册CWin窗体
  8.     void Clear();
  9.     static LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  10. public:
  11.     CWin(const CWin* parent); //建立窗体,parent为NULL时为顶层窗体,否则为子窗体
  12.     ~CWin();
  13.     void setBound(int x, int y, int width, int height);
  14.     void setTitle(const char* title);
  15. };
  16.  
  17. class CMsgLoop{
  18. private:
  19.     MSG m_msg;
  20. public:
  21.     int run();
  22. };
  1. // addin.cpp文件
  2. #include "addin.h"
  3. int CWin::gm_count = 0;
  4. CWin::CWin(const CWin* parent)
  5. {
  6.     DWORD dwStyle = WS_VISIBLE;
  7.     HWND hWndParent = NULL;
  8.     
  9.     if(parent == NULL)
  10.     {
  11.         dwStyle |= WS_OVERLAPPEDWINDOW;
  12.     }
  13.     else
  14.     {
  15.         dwStyle |= WS_CHILD;
  16.         hWndParent = parent->m_hWnd;
  17.     }
  18.  
  19.     RegisterWindow();
  20.     m_hWnd = CreateWindow(
  21.         "CInt.CWin",
  22.         NULL,
  23.         dwStyle,
  24.         0,0,100,100,
  25.         hWndParent,
  26.         0,0,0);
  27.     
  28.     if(m_hWnd){
  29.         gm_count++;
  30.         ::SetProp(m_hWnd, "CWin"this);
  31.     }
  32. }
  33.  
  34. CWin::~CWin()
  35. {
  36.     Clear();
  37. }
  38.  
  39. void CWin::Clear()
  40. {
  41.     if(m_hWnd){
  42.         ::RemoveProp(m_hWnd, "CWin");
  43.         ::DestroyWindow(m_hWnd);
  44.         if(--gm_count<=0) ::PostQuitMessage(0);
  45.     }
  46. }
  47.  
  48. void CWin::RegisterWindow()
  49. {
  50.     static bool fRegistered = false;
  51.     if(!fRegistered)
  52.     {
  53.         WNDCLASS wc={
  54.             0,WndProc,
  55.             0,0,
  56.             ::GetModuleHandle(NULL),
  57.             NULL,LoadCursor(NULL, IDC_ARROW),
  58.             (HBRUSH)(COLOR_BTNFACE+1),
  59.             0,"CInt.CWin"
  60.         };
  61.         if(::RegisterClass(&wc) != 0)
  62.             fRegistered = true;
  63.     }
  64. }
  65. LRESULT CALLBACK CWin::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
  66. {
  67.     if(uMsg == WM_DESTROY)
  68.     {
  69.         CWin *pWin = (CWin*)::GetProp(hwnd, "CWin");
  70.         if(pWin)pWin->Clear();
  71.     }
  72.     else if(uMsg == WM_PAINT)
  73.     {
  74.         RECT rc;
  75.         ::GetClientRect(hwnd, &rc);
  76.         
  77.         PAINTSTRUCT ps;
  78.         HDC hdc = ::BeginPaint(hwnd, &ps);
  79.         char text[100];
  80.         ::GetWindowText(hwnd, text, 100);
  81.         ::DrawText(hdc, text, -1, &rc, DT_CENTER|DT_SINGLELINE|DT_VCENTER);
  82.         ::DrawEdge(hdc, &rc, BDR_RAISEDINNER,BF_RECT);
  83.         ::EndPaint(hwnd, &ps);
  84.     }
  85.     return ::DefWindowProc(hwnd,uMsg,wParam,lParam);
  86. }
  87.  
  88. void CWin::setBound(int x, int y, int width, int height)
  89. {
  90.     if(m_hWnd)
  91.     {
  92.         ::MoveWindow(m_hWnd,x,y,width,height,TRUE);
  93.     }
  94. }
  95.  
  96. void CWin::setTitle(const char *title)
  97. {
  98.     if(m_hWnd)
  99.     {
  100.         ::SetWindowText(m_hWnd, title);
  101.     }
  102. }
  103.  
  104. int CMsgLoop::run()
  105. {
  106.     while(::GetMessage(&m_msg,NULL,0,0))
  107.     {
  108.         TranslateMessage(&m_msg);
  109.         DispatchMessage(&m_msg);
  110.     }
  111.     return (int)m_msg.wParam;
  112. }

在程序里,我们可以这样使用它:

  1. #include "addin.h"
  2.  
  3. int main(int argc, char* argv[])
  4. {
  5.     CWin frame(NULL); //建立窗体
  6.     frame.setBound(100,100,300,200);
  7.     frame.setTitle("hello");
  8.  
  9.     CWin child(&frame); //建立子窗体
  10.     child.setBound(5,5,60,25);
  11.     child.setTitle("child1");
  12.  
  13.     CWin child2(&frame); //建立子窗体
  14.     child2.setBound(5,40,60,25);
  15.     child2.setTitle("child2");
  16.  
  17.     CWin frame2(NULL); //建立另一窗体
  18.  
  19.     CMsgLoop ml; //消息循环
  20.  
  21.     return ml.run();
  22. }

不过现在的目的可不是让它在我们的程序里执行,而是作为脚本给Cint来执行。现在开始吧:

新建一个addin_script.h文件,输入CWin和CMsgLoop的公共成员:

  1. #ifndef __CINT__
  2.     #include "addin.h"
  3. #else
  4.     class CWin{
  5.     public:
  6.         CWin(const CWin* parent);
  7.         ~CWin();
  8.         void setBound(int x, int y, int width, int height);
  9.         void setTitle(const char* title);
  10.     };
  11.     class CMsgLoop{
  12.     public:
  13.         int run();
  14.     };    
  15. #endif

完成后在命令行执行:

cint -c-1 addin_script.h

这时会生成G__cpplink.CG__cpplink.h两个文件,这两个文件是我们的程序和脚本之间的桥梁。把这两个文件
以及前面的addin.cpp加入到我们的项目中,注意要设置G__cpplink.C成"编译为C++代码"(或者干脆扩展名改成.cpp),
否则不能通过编译。

我们主程序的代码为:

  1. #include "G__cpplink.h"
  2. int main(int argc, char* argv[])
  3. {
  4.     G__init_cint("cint");
  5.     G__cpp_setup(); //G__cpp_setup定义在G__cpplink.h里
  6.     G__loadfile("script.cxx");//载入script.cxx,内容见后
  7.     G__calc("main()");
  8.     G__scratch_all();
  9.     return 0;
  10. }

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看看效果。
总结一下上面的步骤:

  1. 首先,编写好你要嵌入脚本的类、函数或类型定义等东东
  2. 然后,把公开给脚本的部分(如类的public部分、指定的类型定义等)重新声明一下保存为新的头文件。
  3. 再然后用“cint -c-1 头文件”或"cint -c-2 头文件"(分别对应C++和C代码)生成脚本嵌入函数。
    用cint读取头文件时会带有__CINT__宏定义,我们可以利用这个特性把脚本用的声明和程序用的声明放到
    一个文件里(就象这个例子里做的一样)
  4. 最后,调用嵌入函数G__cpp_setup()或G__c_setup()把这我们写好的东东嵌入到脚本中供脚本使用。
复制链接 网友评论 收藏本文 关闭此页
上一条: VC、VC++、C++、C它们有什么区别  下一条: 用Cint解析C++脚本
夜鹰教程网成立于2008年,目前已经运营了将近 13 年,发布了大量关于 html5/css3/C#/asp.net/java/python/nodejs/mongodb/sql server/android/javascript/mysql/mvc/easyui/vue/echarts原创教程。 我们一直都在坚持的是:认证负责、一丝不苟、以工匠的精神来打磨每一套教程,让读者感受到作者的用心。我们默默投入的时间,确保每一套教程都是一件作品,而不是呆板的文字和视频! 目前我们推出在线辅导班试运营,模式为一对一辅导,教学工具为QQ。我们的辅导学科包括 java 、android原生开发、webapp开发、商城开发、C#和asp.net开发,winform和物联网开发、web前端开发,但不仅限于此。 普通班针对的是国内学员,例如想打好基础的大学生、想转行的有志青年、想深入学习的程序员、想开发软件的初学者或者业余爱好者等。 就业办针对即将毕业上岗的大四学生,或者打算转行的初级开发工程师。 留学生班针对的是在欧美、加拿大、澳洲、日本、韩国、新加坡等地留学的中国学子,目的是让大家熟练地掌握编程技能,按时完成老师布置的作业,并能顺利地通过考试。 详细咨询QQ:1416759661   夜鹰教程网  基于角色的权限管理系统(c-s/b-s)。
  夜鹰教程网  基于nodejs的聊天室开发视频教程
  夜鹰教程网  Git分布式版本管理视频教程
  夜鹰教程网  MVC+EasyUI视频教程
  夜鹰教程网  在线考试系统视频教程
  夜鹰教程网  MongoDB视频教程。
  夜鹰教程网 Canvas视频教程
  夜鹰教程网 报表开发视频教程
  热点推荐
C++从零开始学编程
C++ 数组array与vector的比较
VC、VC++、C++、C它们有什么区别
SQLite在VC下的使用
五种区别C++内存分配的方法
用Cint解析C++脚本
C打开文件的追加参数
C++ Builder 访问 USB 口的方法
C++中强制转换函数总结
为C++脚本加入新元素
C/C++编程中无所不在的指针概念
C++程序调用数据库的方法
内存泄漏是编程中常常见到的一个问…
C++中指针入门的最好的文章
C++编译错误解决方法
  最近更新
Python操作EXCEL表格
Python 优缺点
使用selenium爬取商城数据代码
Windows消息机制详解
SQLite在VC下的使用
五种区别C++内存分配的方法
VC的dll进行profile
C打开文件的追加参数
C/C++编程中无所不在的指针概念
C++从零开始学编程
VC、VC++、C++、C它们有什么区别
为C++脚本加入新元素
用Cint解析C++脚本
C++ Builder 访问 USB 口的方法
C++中强制转换函数总结

关于我们 | 网站建设 | 技术辅导 | 常见问题 | 联系我们 | 友情链接

夜鹰教程网 版权所有 www.yyjcw.com All rights reserved 备案号:蜀ICP备08011740号3