zoukankan      html  css  js  c++  java
  • C++混合编程之idlcpp教程Lua篇(2)

        在上一篇 C++混合编程之idlcpp教程(一) 中介绍了 idlcpp 工具的使用。现在对 idlcpp 所带的示例教程进行讲解,这里针对的 Lua 语言的例子。首先看第一个示例程序 LuaTutorial0。像很多语言的第一个例子一样,是一个打印 Hello world 的程序。用Visual Studio 2015打开解决方案文件 tutorialsLuaTutorialsLuaTutorials.sln,其下已经有多个工程文件。

     

    在工程LuaTutorial0中,已经加入了三个文件,分别是 LuaTutorial0.cpp, Tutorial0.i, tutorial0.lua。首先看Tutorial0.i内容如下:

    //tutorial
    
    ###include <stdio.h>
    
    namespace tutorial
    {
        struct Test
        {
            static void Run();
        };
        #{
        inline void Test::Run()
        {
            printf("Hello World!");
        }
        #}
    }

    看起来和C++代码较为相似。编译Tutorial0.i,将会生成Tutorial0.h,Tutorial0.mh,Tutorial0.ic,Tutorial0.mc四个文件。其中Tutorial0.h内容如下:

    //DO NOT EDIT THIS FILE, it is generated by idlcpp
    //http://www.idlcpp.org
    
    #pragma once
    
    
    #include <stdio.h>
    
    
    #line 4 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
    namespace tutorial
    
    #line 5 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
    {
    
    #line 6 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
        struct Test
    
    #line 7 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
        {
        public:
    
    
    #line 8 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
            static void Run();
    
    #line 9 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
        };
    
        inline void Test::Run()
        {
            printf("Hello World!");
        }
        
    
    #line 16 "D:/GitHub/idlcpp/tutorials/Common/Tutorial0.i"
    }

    因为在编译.i文件时指定了-ld选项,所以生成的.h文件中其中有许多#line指令,这是为下一步C++编译时能够定位错误到.i中的位置,而不是定位到.h上。修改编译选项,去掉-ld选项,重新编译,得到的结果如下:

     

    //DO NOT EDIT THIS FILE, it is generated by idlcpp
    //http://www.idlcpp.org
    
    #pragma once
    
    
    #include <stdio.h>
    
    namespace tutorial
    {
        struct Test
        {
        public:
    
            static void Run();
        };
    
        inline void Test::Run()
        {
            printf("Hello World!");
        }
        
    }

     

    这样看起来比较清爽了,请和上面的Tutorial0.i内容对照一下,基本上内容差不多。下面详细解释一下,首先是第一行

     //tutorial

    这是注释,idlcpp和C++一样用//表示单行注释,用/**/表示一块注释。 

    ###include <stdio.h>

    idlcpp只分析接口的声明,而C++头文件中一般还会出现其他的内容。此处idlcpp提供了将.i文件中的部分内容直接复制到.h的方法,一共有三种

    1. ##,表示将后续的一整行复制到.h的相应位置上,类似C++中的//注释一行。
    2. #{ 和 #},将在这两个符号之间的内容复制到.h的相应位置上,类似C++中的/*和*/注释一大块。
    3. #,表示将后续的一个标识符或整数复制到相应的位置。

    这一行表示将#include <stdio.h>复制到.h中,下面的printf要用到这个头文件。

    namespace tutorial 以及对应的{}。

    namespace 和C++中的概念是一样的,会原样输出到.h中。

    struct Test 以及对应的{}; 。

    这个也和C++中概念类似,会原样输出到.h中。

    下面.h文件中多了一行

    public:

    在idlcpp中声明的数据成员以及成员函数都被认为是public的,所以此处无脑加了这一行。

    static void Run(); 这一行两边也是一样的,声明一个静态成员函数。

    #{

    inline void Test::Run()

    {

      printf("Hello World!");

    }

    #}

    如上所述,idlcpp将#{和#}之间的内容复制到.h中。因为idlcpp只处理函数声明,不能处理其实现代码,所以无法向C++一样将其实现代码放在类的声明中,只能写在外面。此处为了少写一个.cpp文件,就用内联函数的方式写在头文件中。

    文件Tutorial0.ic中没有实质性的内容。

    文件Tutorial0.mh和Tutorial0.mc用于构建对应的元数据信息,具体内容牵涉太多,暂时不做解释。

    再来看一下LuaTutorial0.cpp的内容

    #include <tchar.h>
    #include <string>
    #include <windows.h>
    
    #include "lua.hpp"
    #include "../../../paf/src/paflua/LuaWrapper.h"
    #include "../../Common/Tutorial0.h"
    #include "../../Common/Tutorial0.mh"
    #include "../../Common/Tutorial0.ic"
    #include "../../Common/Tutorial0.mc"
    
    #if defined(_DEBUG)
    #pragma comment(lib,"pafcore_d.lib")
    #pragma comment(lib,"paflua_d.lib")
    #pragma comment(lib,"lua53_d.lib")
    #else
    #pragma comment(lib,"pafcore.lib")
    #pragma comment(lib,"paflua.lib")
    #pragma comment(lib,"lua53.lib")
    #endif
    
    
    void GetExePath(std::string& path)
    {
        char fileName[MAX_PATH];
        GetModuleFileName(0, fileName, sizeof(fileName));
        const char* end = _tcsrchr(fileName, '\');
        path.assign(fileName, end + 1);
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        int error;
        lua_State *L = luaL_newstate();
        luaL_openlibs(L);
        luaopen_paflua(L);
        std::string path;
        GetExePath(path);
        path += "tutorial0.lua";
        error = luaL_loadfile(L, path.c_str()) || lua_pcall(L, 0, 0, 0);
        if (error) 
        {
            fprintf(stderr, "%s
    ", lua_tostring(L, -1));
            lua_pop(L, 1);
        }
        lua_close(L);
        return 0;
    }

    #include "lua.hpp"

    这一行引入lua头文件

    #include "../../../paf/src/paflua/LuaWrapper.h"

    这一行引入lua插件头文件

    #include "../../Common/Tutorial0.h"

    #include "../../Common/Tutorial0.mh"

    #include "../../Common/Tutorial0.ic"

    #include "../../Common/Tutorial0.mc"

    这几行将由Tutorial0.i编译的结果包含进来,这样编译后就会将对应的元数据信息注册到系统中,从而能够让脚步语言访问到。

     main()函数中是一个运行一个lua脚步的基本过程。其中

    luaopen_paflua(L);

    这一行在lua虚拟机中加载插件。

    最后看一下tutorial0.lua文件的内容

     

    paf.tutorial.Test.Run();

    这句代码表示调用C++中的::tutorial::Test::Run();

    所有由idlcpp生成的数据类型都是在paf名字下,可以理解为lua中的名字paf等价于C++中的全局名字空间。在C++中,Run函数的全名可以认为是::tutorial::Test::Run,在lua中即为paf.tutorial.Test.Run。

    编译链接后,执行结果如下图:

    可以看到Lua正确调用了C++中的函数。

     
  • 相关阅读:
    项目中 2个或者多个EF模型 表名称相同会导致生成的实体类 覆盖的解决方法
    Validation failed for one or more entities. See ‘EntityValidationErrors’解决方法;关于如何查看 EntityValidationErrors 详细信息的解决方法
    深夜杳杳
    我在学习
    IIS下新建虚拟目录
    Win10资源管理器异常
    Docker笔记三:Docker数据卷和DockerFile
    Docker笔记二:Docker拷贝,提交,进入容器和阿里云加速
    ElasticSearch7.x系列三:Logstash的使用
    ElasticSearch7.x系列二:Kibana的使用和C#的Nest客户端
  • 原文地址:https://www.cnblogs.com/fdyjfd/p/5294853.html
Copyright © 2011-2022 走看看