zoukankan      html  css  js  c++  java
  • 为Lua5.3编写C模块简单示例

    为Lua5.3编写C模块简单示例

    一、编译安装Lua5.3

    MSVC 命令行安装脚本:

    @echo off
    md bin
    md lib
    md include
    cd src
    
    cl /c /nologo /W3 /O2 /Ob1 /Oi /Gs /MD /D_CRT_SECURE_NO_DEPRECATE l*.c
    ren lua.obj lua.o
    ren luac.obj luac.o
    lib /OUT:lua53.lib *.obj
    copy lua53.lib ..liblua53.lib
    del *.o *.obj *.exp *.lib *.dll *.exe
    
    cl /c /nologo /W3 /O2 /Ob1 /Oi /Gs /MD /D_CRT_SECURE_NO_DEPRECATE /DLUA_BUILD_AS_DLL l*.c
    ren lua.obj lua.o
    ren luac.obj luac.o
    link /DLL /IMPLIB:lua53.lib /OUT:lua53.dll *.obj
    link /OUT:lua53.exe lua.o lua53.lib
    link /OUT:luac53.exe luac.o *.obj
    copy lua53.exp ..inlua53.exp
    copy lua53.lib ..inlua53.lib
    copy lua53.dll ..inlua53.dll
    copy lua53.exe ..inlua53.exe
    copy luac53.exe ..inluac53.exe
    del *.o *.obj *.exp *.lib *.dll *.exe
    
    copy lauxlib.h ..includelauxlib.h
    copy lua.h ..includelua.h
    copy lua.hpp ..includelua.hpp
    copy luaconf.h ..includeluaconf.h
    copy lualib.h ..includelualib.h
    cd ..

    打开vs开发人员命令提示,执行此脚本,进行编译。

    生成的目录文件结构:

    使用VS编写Lua的C模块时, VS的配置。

     

    C模块mytest.h头文件源码:

    /* Start of mytest.h */
    
    #ifndef __MYTEST_H__
    #define  __MYTEST_H__
    
    #ifdef __unix__
    
    #define DllExport extern
    
    #else
    
    #define DllExport  __declspec( dllexport )
    
    #endif // __unix__
    
    #ifdef __cplusplus
    
    #include <lua.hpp>
    
    #else
    
    extern "C" {
    #include "lua.h"
    #include "lualib.h"
    #include "lauxlib.h"
    }
    
    #endif // __cplusplus
    
    
    #ifdef __cplusplus
    extern "C" { // 告诉编译器以C的方式编译, 防止变量名称及函数名称粉碎问题
    #endif // __cplusplus
    
    
    /* 此函数为C库中的“特殊函数", 在Windows系统中必须使用"__declspec( dllexport )"导出, 在类Unix上使用"extern"导出
     * 通过调用它注册所有C库中的函数,并将它们存储在适当的位置。
     * 此函数的命名规则应遵循:
     * 1、使用"luaopen_"作为前缀。
     * 2、前缀之后的名字将作为"require"的参数, 所以此名字必须和生成的dll同名否则找不到对应的库
     */
    DllExport int luaopen_cl01(lua_State* L);
    
    #ifdef __cplusplus
    } /* extern "C" */
    #endif // __cplusplus
    
    #endif // __MYTEST_H__
    
    /* End of mytest.h */

    C模块mytest.c文件源码:

    /* Start of mytest.c */
    
    #include <stdio.h>
    #include <math.h>
    #include <stdarg.h>
    #include <stdlib.h>
    
    #include "mytest.h"
    
    #ifdef __cplusplus
    extern "C" { // 告诉编译器以C的方式编译, 防止变量名称及函数名称粉碎问题
    #endif // __cplusplus
    
    /* 所有注册给Lua的C函数具有
     * "typedef int (*lua_CFunction) (lua_State *L);"的原型。
     */
    static int l_sin(lua_State *L)
    {   
        // 如果给定虚拟栈中索引处的元素可以转换为数字,则返回转换后的数字,否则报错。
        double d = luaL_checknumber(L, 1);
        lua_pushnumber(L, sin(d));  /* push result */
    
        /* 这里可以看出,C可以返回给Lua多个结果,
         * 通过多次调用lua_push*(),之后return返回结果的数量。
         */
        return 1;  /* number of results */
    }
    
    /* 需要一个"luaL_Reg"类型的结构体,其中每一个元素对应一个提供给Lua的函数。
     * 每一个元素中包含此函数在Lua中的名字,以及该函数在C库中的函数指针。
     * 最后一个元素为“哨兵元素”(两个"NULL"),用于告诉Lua没有其他的函数需要注册。
     */
    static const struct luaL_Reg cl01[] = {
        {"mysin", l_sin},
        {NULL, NULL}
    };
    
    /* 此函数为C库中的“特殊函数", 在Windows系统中必须使用"__declspec( dllexport )"导出, 在类Unix上使用"extern"导出
     * 通过调用它注册所有C库中的函数,并将它们存储在适当的位置。
     * 此函数的命名规则应遵循:
     * 1、使用"luaopen_"作为前缀。
     * 2、前缀之后的名字将作为"require"的参数, 所以此名字必须和生成的dll同名否则找不到对应的库
     */
    DllExport int luaopen_cl01(lua_State* L)
    {
        /* void luaL_newlib (lua_State *L, const luaL_Reg l[]);
         * 创建一个新的"table",并将"l"中所列出的函数注册为"table"的域。
         */ 
        luaL_newlib(L, cl01);
    
        return 1;
    }
    
    #ifdef __cplusplus
    } /* extern "C" */
    #endif // __cplusplus
    
    /* End of mytest.c */

    点击生成,产生以下文件

    我们只需要将 cl01.dll 文件,拷贝到Lua的工作目录下即可。

    LuaFile1.lua 文件源码:

    --region LuaFile1.lua
    --Date
    --此文件由[BabeLua]插件自动生成
    
    io.write(string.format("-------->>> %s <<<--------
    ", "testing ...")) -- 此函数不会自动换行
    local cl01lib = require("cl01")
    print("mysin(3.14 /2) result: ", cl01lib.mysin(3.14 /2))
    
    
    -- 通过调用控制台命令行使程序暂停
    -- os.execute("pause")
    
    --endregion

    运行结果现象:

  • 相关阅读:
    C基础之移位操作
    实现itoa()
    Python的time模块的clock方法在不同平台的效果不同
    __stdcall与__cdecl之区别浅析及相关知识
    Python 字典 dictionary changed size during iteration
    Windows下printf输出long long类型
    inotify也会爆棚
    一条对“失控的腾讯帝国:企鹅无法把控手机市场”的评论
    imfunny程序员的增量发展
    程序员第一定律:关于技能和收入
  • 原文地址:https://www.cnblogs.com/lsgxeva/p/7751724.html
Copyright © 2011-2022 走看看