我是C++语言的忠实拥趸,由于在上学时经历了资源匮乏的DOS时代,对C/C++这种更加接近硬件的语言由衷的喜爱。一直以来也是已C++作为工作的语言,对别的语言那是不屑一顾。在java火爆流行的时候,没有去深入了解过。现在看其实是一种损失,若非如此这篇博文或许能早几年就写出来了。然后由于工作的关系学了一点C#,在看到关于元数据的时候,萌生了在C++中实现类似功能的念头。后来接触过一些脚本语言,发现借助元数据是实现C++和脚本语言混合编程的好办法。

最初的时候,我尝试使用模板来实现这样的功能。经过一段时间的实践后,发现有些问题不易解决,而且用起来也不太方便,写了一半就放弃了。后来联想到微软使用idl这种接口描述语言来定义COM接口,决定使用类似的方法。大体就是定义一种接口描述语言,通过相应的编译器生成对应的C++头文件以及元数据描述代码,同时提供一个运行时库作为使用这些元数据的基础。这个编译器就是idlcpp,意为用接口描述语言生成C++代码,当然此处的idl不是微软的idl,只不过因意义相似,也用了同样的英文简写。

此idl语言到目前为止支持如下概念:命名空间,类和结构,数据成员,属性,方法,静态成员,虚函数,函数重载,运算符重载,多重继承,枚举,模板等。其中关键字大部分照抄的C++,所以乍看起来比较像C++代码。

除了idlcpp这个编译器外,还有一个基础的运行时库,以及针对不同的脚本语言相应的插件(目前只有lua和python),使用的开发工具是Visual Studio 2015,对非MS平台不太熟悉,所以暂时编译器只支持Windows平台(用到了一些Windows特有的函数)。不过运行时库没有用到特定平台的功能,较易移植到其他平台。此外还写了一些示例代码。上述所有代码托管在github上:https://github.com/fdyjfd/idlcpp/,另外还建了一个网站:http://idlcpp.org/ 目前网站还没什么内容,以后慢慢去丰富。

下面进入正题,先从工具的使用开始。

Idlcpp命令行工具

Idlcpp可以从github上下载代码编译得到,另外我也在网上放了一份已经编译好的执行文件,可以从 http://files.cnblogs.com/files/fdyjfd/idlcpp.zip 下载直接使用。若要自己编译idlcpp,请先从github上获取源代码。源代码结构如下:

其中idlcpp目录下是idlcpp的源代码。paf目录下是基础运行时库与脚本插件的代码。tutorials下是一些示例教程。目录bin是用来放置编译生成的dll及exe文件的,示例的lua和python脚本也放在这里。

编译idlcpp要用到第三方工具flex和bison。这两个工具可以从 https://sourceforge.net/projects/gnuwin32/ 下载。安装这两个工具后将其所在目录设置到环境变量Path中,以便编译时可以找到它们。编译成功后会在bin目录下生成idlcpp.exe。也可以下载我上传的以编译好的zip压缩包,将其解压到bin目录下,然后将bin目录也设置到环境变量Path中;或者将其解压到windows目录下供后面使用。

idlcpp通过编译接口描述文件(默认扩展名为.i),生成4个C++代码文件,分别是:

1. 相应的头文件(默认扩展名为.h)。

2. 内置函数的实现文件(默认扩展名为.ic)。

3. 元数据包装类的头文件(默认扩展名为.mh)。

4. 元数据包装类的实现文件(默认扩展名为.mc)。

运行cmd,进入idlcpp所在目录,运行命令idlcpp –h,结果如下图所示:

各选项含义为:

-h  显示帮助信息。

-ld  在生成的头文件中加入 #line 指令,用于编译器发现错误时正确定位到 .i文件中的对应位置。

-pc  指定运行时库pafcore头文件所在的路径。

-mp 元数据包装类的名字是根据对应类型的名字以及所在的命名空间生成的,此选项用于指定生成的元数据包装类型名的后缀,默认值为”_Type”。

-sp  用于生成子类代理类名字的后缀,默认值为”_Proxy”。子类代理类用于模拟脚本继承C++类型进而重写虚函数的功能。

-ic  指定内置函数的实现文件名的后缀,默认为”.ic”。

-mh  指定元数据头文件的后缀,默认为”.mh”。

-mc  指定元数据实现文件的后缀,默认为”.mc”。

-em  在Visual C++中,需用__declspec(dllexport)和__declspec(dllimport)处理dll中导出函数的情形,一般情况下用一个宏定义上述两者,在生成的元数据代码中也需要导出一些函数到dll中,此时idlcpp把此处定义的宏插到相应的代码处。

-I 将指定路径加入#import命令的搜索路径中。

编译paf

用Visual Studio 2015打开解决方案文件paf\build\vs2015\paf.sln

paf 中有3个工程,分别为:

1.  pafcore,这是基础的运行时库,提供了元数据的实现。相当于.Net中的System.Reflection或者java中的java.lang.reflect。

2.  paflua,这是lua的插件,用于pafcore和lua之间的交互,使用lua语言可以通过这个插件访问用户导出的各种功能。

3.  pafpython,这是python的插件,用于pafcore和python之间的交互,使用python语言可以通过这个插件访问用户导出的各种功能。

在pafcore工程中除了C++代码文件之外,还有许多idl的代码文件(扩展名为.i),如下图:

这些文件都是需要用idlcpp编译的。此处通过Custom Build Tool设置编译命令和选项,查看任意一个.i文件的属性,入下图所示:

在Visual Studio中可以通过属性文件简化Custom Build Tool的设置,pafcore所使用的属性文件在paf\build\vs2015\pafcore\pafcore.props。

设定好idlcpp.exe的路径以便系统可以找到它(比如设置环境变量Path或将其复制到Windows目录下)后即可编译pafcore工程。

工程paflua依赖lua,先从lua官网下载源文件编译后,再设置合适的头文件以及库文件路径,即可编译。

工程pafpython依赖python,先从python官网下载源文件编译后,再设置合适的头文件以及库文件路径,即可编译。

以上三个工程都会编译为Dll文件,默认放置在bin目录下。若是release版,文件名分别为pafcore.dll, paflua.dll和pafpython.dll。若是debug版,文件名分别为pafcore_d.dll, paflua_d.dll和pafpython_d.dll。

到现在为止,准备工作已经完成,下次开始介绍 tutorials 下的各个例子程序。

Lua语言的例子从这 C++混合编程之idlcpp教程Lua篇(2) 开始

Python语言的例子从这 C++混合编程之idlcpp教程Python篇(2) 开始

C++混合编程之idlcpp教程(一)的更多相关文章

  1. C++混合编程之idlcpp教程Python篇(9)

    上一篇在这 C++混合编程之idlcpp教程Python篇(8) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相比,工程PythonTutorial7中除了四个文件PythonTu ...

  2. C++混合编程之idlcpp教程Lua篇(9)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(8) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相比,工程LuaTutorial7中除了四个文件LuaTutorial7.c ...

  3. C++混合编程之idlcpp教程Python篇(8)

    上一篇在这 C++混合编程之idlcpp教程Python篇(7) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程PythonTutorial6中,同样加入了四个文件:Pyt ...

  4. C++混合编程之idlcpp教程Lua篇(8)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(7) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程LuaTutorial6中,同样加入了四个文件:LuaTutori ...

  5. C++混合编程之idlcpp教程Python篇(7)

    上一篇在这 C++混合编程之idlcpp教程Python篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与PythonTutorial4工程相似,工程PythonTutorial5中,同 ...

  6. C++混合编程之idlcpp教程Lua篇(7)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(6) 第一篇在这 C++混合编程之idlcpp教程(一) 与LuaTutorial4工程相似,工程LuaTutorial5中,同样加入了四个文件: ...

  7. C++混合编程之idlcpp教程Python篇(6)

    上一篇在这 C++混合编程之idlcpp教程Python篇(5) 第一篇在这 C++混合编程之idlcpp教程(一) 工程PythonTutorial4中加入了四个文件:PythonTutorial4 ...

  8. C++混合编程之idlcpp教程Lua篇(6)

    上一篇在这 C++混合编程之idlcpp教程Lua篇(5) 第一篇在这 C++混合编程之idlcpp教程(一) 工程LuaTutorial4中加入了四个文件:LuaTutorial4.cpp, Tut ...

  9. C++混合编程之idlcpp教程Python篇(5)

    上一篇在这  C++混合编程之idlcpp教程Python篇(4) 第一篇在这 C++混合编程之idlcpp教程(一) 与前面的工程相似,工程PythonTutorial3中,同样加入了三个文件:Py ...

随机推荐

  1. html-css实例

    <!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <title&g ...

  2. makefile学习小结

    =============2016/08/15================ 上午完成makefile的试验,缩短了代码量,现在make强大,有缺省的变量,能自己推导关系,不需要gcc –MM -M ...

  3. centos6.x下手工安装二进制Docker v1.1x

    Docker在 centos 6.x 下面默认最新的版本是1.7, 然而这个并不符合我的实际需求, 尤其我需要 docker-compose 来作为编配工具部署swarm, 所以只有使用二进制的安装包 ...

  4. Python 2.7_Second_try_爬取阳光电影网_获取电影下载地址并写入文件 20161207

    1.昨天文章http://www.cnblogs.com/Mr-Cxy/p/6139705.html 是获取电影网站主菜单 然后获取每个菜单下的电影url  2.今天是对电影url 进行再次解析获取下 ...

  5. {Reship}{C#}{GDI+}GDI+画笔,线,区域类型

    =================================================================================== This article is ...

  6. 9.springMVC中的拦截器

    springMVC中的拦截器大概大致可以分为以下几个步骤去学习: 1.自定义一个类实现HandlerInterceptor接口,这里要了解其中几个方法的作用 2.在springMVC的配置文件中添加拦 ...

  7. 如何在A用户下建立视图,这个视图是A的表与B的表进行关联的?

    这个前提条件是,同一个数据库,不同用户!!!如果是不同数据库,就要用dblink了 一开始,我直接创建视图,但是提示“权限不足”: 于是我是用A登陆,直接用select * from B.sa_tas ...

  8. [转]LIBSVM-3.18在python环境下的使用

    http://blog.csdn.net/lj695242104/article/details/39500039 1)安装Python,直接去官方网站 2)运行“cmd”,直接输入python,查看 ...

  9. oracle中rownum和rowid的区别

    rownum和rowid的区别总括: rownum和rowid都是伪列,但是两者的根本是不同的. rownum是根据sql查询出的结果给每行分配一个逻辑编号,所以你的sql不同也就会导致最终rownu ...

  10. (五) 一起学 Unix 环境高级编程 (APUE) 之 进程环境

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...