Calling Lua functions : using C++ language

Audience

This article was written for C++ developers that want extend your application with Lua programming Language.

这篇文章是为那些想用Lua语言扩展应用程序的C++程序员而写。

Introduction

One of the most common tasks when you use Lua in C++ application is call Lua functions, but this can be tiresome, you need use a lot of functions of LUA C API (lua_getglobal, lua_pushnumber, lua_pushstring, lua_tointeger and so on) to call one simple Lua function. Here I will show C++ templates that can make your life easy.

调用Lua函数是在C++应用程序中使用Lua最常见的任务之一。这个工作很烦人。你需要使用许多LUA C API(lua_getglobal, lu_pushnumber, lua_pushstring, lua_tointeger等等)来调用一个简单的Lua函数。在这里,我会展示让你的工作变得轻松的C++模板。

Interface

The interface is very easy see:. Think that you have these four Lua function and you want to call in your application:

这个接口很容易明白:想想你有下面4个Lua函数,你想在你的应用程序中调用他们。

Listing 1 – Lua Functions – test.lua
--------------------------------------------------------------------------------------

var = 10;

function sum4(a, b, c, d)

      return a+b+c+d;

end

function catenate(a, b)

      return a.." and "..b;

end

function incVar(value)

      var = var+value;

end

function getVar()

      return var;

end

--------------------------------------------------------------------------------------

Then what you need to call these function is use:

然后调用这些函数,你需要使用:

  • LuaCall template class.

The basic way are you instantiate LuaCall with types of your Lua function receive and return, for sample:

基本的方法是你用你的Lua函数的参数和返回值的类型实例化LuaCall模板,比如:

float a = LuaCall<float, int, float, int, int>(L, "sum4").call(5, 1.5, 5, 5); 
See complete sample below (listing 2).

Listing 2 – using LuaCall – main.cpp

--------------------------------------------------------------------------------------

#include


<iostream>

#include "LuaCall.h"

extern "C" {

#include <lua.h>

#include <lauxlib.h>

#include <lualib.h>

}

int main()

{

try

{    

      lua_State *L;

      L = luaL_newstate();

      if(luaL_loadfile(L, "list1.lua") || lua_pcall(L, 0, 0, 0))

{

            throw std::string(std::string(lua_tostring(L, -1)));

      }

           

      std::cout <<LuaCall<float, int, float, int, int>(L, "sum4").call(5, 1.5, 5, 5) << std::endl;

      std::cout << LuaCall<std::string, std::string, std::string>(L, "catenate").call("Renato", "Bianca") << std::endl;

      LuaCall<NullT, int>(L, "incVar").call(10);

      std::cout << LuaCall<int>(L, "getVar").call() << std::endl;

           

      if(L != NULL)

      {

            lua_close(L);

      }

}

catch (const std::string &e)

{

      std::cout << e << std::endl;

}

      return 0;

}

Implementation

This is the implementation of LuaCall:

这是LuaCall的实现:

Listing 3 –LuaCall imp – LuaCall.h

--------------------------------------------------------------------------------------

template


<

typename T1,

typename T2

>

class  Duo

{

};

// type that represents unused type parameters

class  NullT

{

};

class LuaCallBase

{

public:

      LuaCallBase(lua_State *luaState, const std::string& functionName)

      {

            L = luaState;

            lua_getglobal(L, functionName.c_str());

      }

protected:

      void push(const int &value)

      {

            lua_pushinteger(L, value);

      }

      void push(const float &value)

      {

            lua_pushnumber(L, value);

      }

      void push(const double &value)

      {

            lua_pushnumber(L, value);

      }

      void push(const std::string &value)

      {

            lua_pushstring(L, value.c_str());

      }

      void get(int &value) const

      {

            value = lua_tointeger(L, -1);

      }

      void get(float &value) const

      {

            value = lua_tonumber(L, -1);

      }

      void get(double &value) const

      {

            value = lua_tonumber(L, -1);

      }

      void get(std::string &value) const

      {

             value = (char*)lua_tostring(L, -1);

      }

      void get(NullT &value) const

      {

      }

protected:

      lua_State *L;

};

template <

typename TR,

typename T1 = NullT,

typename T2 = NullT,

typename T3 = NullT,

typename T4 = NullT

>

class  LuaCall

      : public Duo<TR, typename LuaCall<T1,T2,T3,T4,NullT> >

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(T1 a1, T2 a2, T3 a3, T4 a4)

      {

            TR returnValue;

            push(a1);

            push(a2);

            push(a3);

            push(a4);

            if(lua_pcall(L, 4, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <

typename TR,

typename T1,

typename T2,

typename T3

>

class  LuaCall<TR,T1,T2,T3,NullT>

      : public Duo<TR,T1>

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(T1 a1, T2 a2, T3 a3)

      {

            TR returnValue;

            push(a1);

            push(a2);

            push(a3);

            if(lua_pcall(L, 3, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <

typename TR,

typename T1,

typename T2

>

class  LuaCall<TR,T1,T2,NullT,NullT>

      : public Duo<TR,T1>

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(T1 a1, T2 a2)

      {

            TR returnValue;

            push(a1);

            push(a2);

            if(lua_pcall(L, 2, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <

typename TR,

typename T1

>

class  LuaCall<TR,T1,NullT,NullT,NullT>

      : public Duo<TR,T1>

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(T1 a1)

      {

            TR returnValue;

            push(a1);

            if(lua_pcall(L, 1, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <typename TR>

class  LuaCall<TR,NullT,NullT,NullT,NullT>

      : public Duo<TR,NullT>

      , public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      TR call(void)

      {

            TR returnValue;

            if(lua_pcall(L, 0, 1, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

            get(returnValue);

            return returnValue;

      }

};

template <>

class  LuaCall<NullT,NullT,NullT,NullT,NullT>

      : public LuaCallBase

{

public:

      LuaCall(lua_State *L, const std::string& functionName)

            : LuaCallBase(L, functionName)

      {

      }

      void call(void)

      {

            if(lua_pcall(L, 0, 0, 0) != 0)

            {

                  throw std::string(std::string(lua_tostring(L, -1)));

            }

      }

};

Bibliography
Roberto Ierusalimschy
Programming in Lua – 2nd ed. (
http://www.inf.puc-rio.br/~roberto/pil2/)
ISBN 85-903798-2-5

David Vandevoorde - Nicolai M. Josuttis
C++ Templates - The Complete Guide
ISBN 0-201-73484-2
Lua.org
http://www.lua.org/
Mailing list
http://www.lua.org/lua-l.html
Community
http://www.lua.org/community.html
Embeddable scripting with Lua
http://www-128.ibm.com/developerworks/linux/library/l-lua.html
The Web Links listed here may not be valid in the future.





License

This article, along with any associated source code and files, is licensed under The MIT License


原文地址


http://www.codeproject.com/Articles/17469/Calling-Lua-functions-using-C-language




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
当您尝试通过Java Web服务调用SOAP(Simple Object Access Protocol)时,遇到`java.util.ConcurrentModificationException`通常意味着在并发修改一个集合(如ArrayList或LinkedList)时,集合内部的结构被其他线程意外地更改了。在处理Web服务请求时,如果代码中存在这样的异常,可能是以下几个原因: 1. **并发安全问题**:如果在遍历或操作集合的同时,集合本身正在被其他线程更新(比如添加或删除元素),这会导致并发修改异常。 2. **未正确同步**:可能是在多线程环境中,对集合的操作没有使用适当的同步机制,如synchronized块或`java.util.concurrent`包下的工具。 3. **循环引用**:在处理复杂的数据结构时,如果没有正确管理引用,可能导致死锁或内存泄漏,从而间接引发此异常。 4. **代码逻辑错误**:可能在编写处理Web服务响应的代码时,无意中对集合进行了修改。 为了解决这个问题,您可以采取以下措施: - **检查并修复并发代码**:确保在修改集合时,其他线程不会同时访问它。 - **使用`Collections.synchronizedList`或`CopyOnWriteArrayList`**:这些集合类可以提供线程安全的遍历或操作。 - **确保资源清理**:在结束对集合的操作之前,确保所有的引用都被适当地释放。 - **审查日志和堆栈跟踪**:找出引发异常的具体代码位置,以便定位和修复问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值