Interaction between Lua and C/C ++ -- C/C ++ exports Dll

Source: Internet
Author: User

 

0. Introduction

Lua is becoming increasingly popular as a mature scripting language. It can also be used as a language for interacting with C/C ++ execution scripts. In addition, the entire Lua library is very small. I installed the latest official version of Lua 5.1, and the entire static link of lua. dll is 164KB. Therefore, Lua is lightweight and especially suitable for lightweight script embedding.

 

We can see from the article name that we want to talk about the interaction between Lua and C/C ++, this section describes how Lua uses C/C ++ to call the dll exported by C/C ++. OK, Let's Go! First, you have to go to Lua official website http://www.lua.org to get the latest version of Lua.

 

1. Preparations

After installing Lua, You need to configure the Lua path in Visual Studio so that your compiler can search for it. For more information about VS2010 configuration, see my blog article "VS2010 C ++ directory configuration. Create a Dll project.

 

We will use a program that displays the Windows dialog box in Lua to briefly introduce it. The program is small but dirty. The procedure is as follows:

 

//

// Export some useful Win32 features.

// Used in Lua.

//

 

 

Extern "C"

{

# Include <lua. h>

# Include <lualib. h>

# Include <lauxlib. h>

# Pragma comment (lib, "lua. lib ")

};

 

 

# Include <Windows. h>

# Include <iostream>

Using namespace std;

 

 

Static const char * const ERROR_ARGUMENT_COUNT = "the number of parameters is incorrect! ";

Static const char * const ERROR_ARGUMENT_TYPE = "parameter type error! ";

 

 

//

// An error is reported.

//

Void ErrorMsg (lua_State * luaEnv, const char * const pszErrorInfo)

{

Lua_pushstring (luaEnv, pszErrorInfo );

Lua_error (luaEnv );

}

 

 

//

// Check whether the number of function call parameters is normal.

//

Void CheckParamCount (lua_State * luaEnv, int paramCount)

{

// Lua_gettop gets the number of elements in the stack.

If (lua_gettop (luaEnv )! = ParamCount)

{

ErrorMsg (luaEnv, ERROR_ARGUMENT_COUNT );

}

}

 

 

//

// Display the Windows dialog box.

// @ Param [in] pszMessage string 1

// @ Param [in] pszCaption string 2

//

Extern "C" int ShowMsgBox (lua_State * luaEnv)

{

Const char * pszMessage = 0;

Const char * pszCaption = 0;

 

// Check whether the number of parameters is correct.

CheckParamCount (luaEnv, 2 );

 

// Extract parameters.

PszMessage = luaL_checkstring (luaEnv, 1 );

PszCaption = luaL_checkstring (luaEnv, 2 );

 

If (pszCaption & pszMessage)

{

: MessageBox (

NULL,

PszMessage,

PszCaption,

MB_ OK | MB_ICONINFORMATION

);

}

Else

{

ErrorMsg (luaEnv, ERROR_ARGUMENT_TYPE );

}

 

// The number of returned values is 0.

Return 0;

}

 

 

//

// Export the function list.

//

Static luaL_Reg luaLibs [] =

{

{"ShowMsgBox", ShowMsgBox },

{NULL, NULL}

};

 

 

//

// Dll entry function. Lua calls the Dll entry function.

//

Extern "C" _ declspec (dllexport)

Int luaopen_WinFeature (lua_State * luaEnv)

{

Const char * const LIBRARY_NAME = "WinFeature ";

LuaL_register (luaEnv, LIBRARY_NAME, luaLibs );

 

Return 1;

}

 

 

//:-)

2. Program Parsing

First, we include the Lua header file and link the file into the database. Note: The Lua header file is in the C style, so it is included with external "C. In this example, the final export function is "ShowMsgBox ".

 

The format of each exported function is:

 

Extern "C" int Export_Proc_Name (luaState * luaEnv );

The structure referred to by luaState * contains the required Lua environment when Lua calls this Dll. So what should Lua do when passing parameters to the function? It is actually done using the luaL_check [type] function. As follows:

 

Const char * pHelloStr = luaL_checkstring (luaEnv, 1 );

 

Double value = luaL_checknumber (luaEnv, 2 );

Int ivalue = luaL_checkint (luaEnv, 3 );

The second parameter of the luaL_check series functions is that when Lua calls this function, it passes the order of parameters from the right to the right (from 1 ).

 

Then we can see that a static luaL_Reg structure array contains a list of all functions to be exported. Finally, a series of operations are completed through an export function of luaopen_YourDllName. YourDllName is the name of your final Dll (excluding the extension ). When you call this Dll in Lua, Lua will find the function corresponding to luaopen_YourDllName Based on the Dll name, and then load the Dll from this function.

 

The format of the Dll entry function is as follows:

 

Extern "C" _ declspec (dllexport)

Int luaopen_WinFeature (lua_State * luaEnv)

{

Const char * const LIBRARY_NAME = "WinFeature ";

LuaL_register (luaEnv, LIBRARY_NAME, luaLibs );

 

Return 1;

}

We use luaL_register to register the library name corresponding to LIBRARY_NAME and the export list corresponding to the luaL_Reg array to the Lua environment corresponding to lua_State.

 

3. Lua call

So how do we call this Dll? First, put the Dll in the directory that Lua can search for-the current directory, the clibs directory under the Lua installation directory ...... Then import the data using the require function.

 

In Lua, if there is only one function call parameter and the parameter is a string, brackets can be omitted during function call. Therefore:

Both require ("YourLibName") and requir "YourLibName" are valid. Copy the generated WinFeature. dll file to drive C and start Lua on drive C. Example:

 

You can see that the function call method is "package name. function name", and the package name is your Dll name. We can use the following method to view all functions in a package:

 

 

For k, v in pairs (PackageName) do

Print (k, v)

End

Then we call the WinFeature. ShowMsgBox function:

 

4. Lua stack details

 

Well, how does the lua_State structure manage the Lua runtime environment? How does Lua PASS Parameters to C/C ++ functions? How does a C/C ++ function return a value to Lua ?...... All of this must begin with the Lua stack.

 

When Lua interacts with C/C ++, The Lua runtime environment maintains a stack-instead of a stack in the traditional sense, it is simulated by Lua. Data transmission between Lua and C/C ++ is completed through this stack. This stack represents the structure referred to by lua_State.

 

4. 1. stack structure Parsing

The stack uses the lua_push series functions to input values to the stack and obtain values from the stack through the luaL_check series. The parameter indexes passed when luaL_check functions are used. For example, when we call the WinFeature. ShowMsgBox ("Hello", "Tip") function, the stack structure is as follows:

The index of the parameter in the stack is the index of the parameter from left to right (starting from 1), and the element index on the top of the stack can also be remembered from-1. The number of elements in the stack can be obtained using lua_gettop. If lua_gettop returns 0, the stack is empty. (Lua_gettop is not a good function name! Haha)

 

 

4. Extract Parameters

When obtaining a value, luaL_check checks whether the value meets The expected type. If not, an exception is thrown. All functions of this series are as follows:

 

LuaL_checkany -- detects any value (which can be nil)

LuaL_checkint -- checks whether a value is a number (double) and converts it to an int value.

LuaL_checkinteger -- checks whether a value is number (double) and converts it to lua_Integer (prtdiff_t). On my machine, ptrdiff_t is defined as int.

LuaL_checklong -- checks whether a value is number (double) and converts it to long

LuaL_checklstring -- checks whether a value is a string and transmits the string length to the [out] parameter to return

LuaL_checknumber -- checks whether a value is a number (double)

LuaL_checkstring -- checks whether a value is string and returns

LuaL_checkudata -- detects custom types

 

4. 3. Pass the return value

When we want to pass the return value to Lua, we can use the lua_push series functions. Each exported function returns an int integer, which is the number of returned values of your exported function. The return value is pushed to the stack through lua_push functions. For example, an Add function:

 

Extern "C" int Add (lua_State * luaEnv)

{

CheckParamCount (luaEnv, 2 );

 

Double left = luaL_checknumber (luaEnv, 1 );

Double right = luaL_checknumber (luaEnv, 2 );

 

Double result = left + right;

Lua_pushnumber (luaEnv, result );

Return 1;

}

We can see that we use lua_pushnumber to push the returned value into the stack, and 1-1 is the number of returned values. The lua_push series functions are as follows:

 

Lua_pushboolean -- press a bool Value

Lua_pushcfunction -- press a lua_CFunction Type C function pointer

Lua_pushfstring -- format a string and return it, similar to sprintf

Lua_pushinteger -- press an int

Lua_pushlightuserdata -- press in the Custom Data Type

Lua_pushliteral -- press a literal string

Lua_pushlstring -- press a string within the specified length

Lua_pushnil -- press the nil value

Lua_pushnumber -- press the lua_Number (double) Value

Lua_pushstring -- press a string

Lua_pushthread -- press into the thread corresponding to the lua_State passed. If this thread is the main thread, 1 is returned.

Lua_pushvalue -- copy the value of the passed index and press it to the top of the stack.

Lua_pushvfstring -- similar to lua_pushfstring

Through these functions, we can flexibly use the high-performance features of C/C ++ to export functions for Lua to call.

From: Zhang's column

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.