当前位置:网站首页>Detailed explanation of mutual call between C language and Lua

Detailed explanation of mutual call between C language and Lua

2022-06-11 06:30:00 Quiet Zhiyuan 2021

1. Write a C call Lua Of Demo Compile operation

add.c Content

// You need include These are a few lua The header file 
#include <stdio.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
lua_State* L;
int
luaadd(int x, int y)
{
    
 int sum;
 /* Function name */
 lua_getglobal(L,"add");
 /* Parameter stack */
 lua_pushnumber(L, x);
 /* Parameter stack */
 lua_pushnumber(L, y);
 /* Start calling functions , Yes 2 Parameters ,1 Return values */
 lua_call(L, 2, 1);
 /* Take out the return value */
 sum = (int)lua_tonumber(L, -1);
 /* Clear the stack of returned values */
 lua_pop(L,1);
 return sum;
}
int
main(int argc, char *argv[])
{
    
 int sum;
 L = luaL_newstate(); /*  establish lua State machine  */
 luaL_openlibs(L); /*  open Lua All in the state machine Lua Standard library  */
 /* load lua Script */
 luaL_dofile(L, "add.lua");
 /* call C function , This will call lua function */
 sum = luaadd(99, 10);
 printf("The sum is %d \n",sum);
 /* eliminate Lua*/
 lua_close(L);
 return 0;
}

add.lua And C In the same category , Write a simple function inside , Give Way C call

function add(x,y)
  print("this is a lua script")
  return x + y
end

Okay , Finally, it's time to use GCC The stage of compilation , direct gcc add.c Let's see if we can .
 Insert picture description here
Sure enough, the report was wrong !

This is because you didn't put add.c The functions inside are linked to the functions we compiled earlier lua Curry caused . How to let him specify which library to link ? see GCC The documentation of -l Parameter can specify the library to link

-l Parameters and -L Parameters
-l Parameters are used to specify the library that the program will link to ,-l The parameter is followed by the library name , So what does a library name have to do with a real library file name ?
Take the math library , His library name is m, His library file name is libm.so, It's easy to see , Put the header of the library file name lib And tail .so It's the name of the library

2. C Language call Lua Compilation problem summary

2.1 Correct compile command

Link to the original text :https://blog.csdn.net/uisoul/article/details/60137134

gcc -o test test.c -llua -lm -ldl​

Let's try again , Compiled this time : test

Successful implementation !

2.2 problem 1: The lack of -lm Parameters

/usr/local/lib/liblua.a(lobject.o): In function `numarith': lobject.c:(.text+0xc8d): undefined reference to `fmod' lobject.c:(.text+0xcb8): undefined reference to `pow' /usr/local/lib/liblua.a(lvm.o): In function `luaV_execute': 
lvm.c:(.text+0x2068): undefined reference to `pow' lvm.c:(.text+0x211c): undefined reference to `fmod' /usr/local/lib/liblua.a(lmathlib.o): In function `math_log10': lmathlib.c:(.text+0x21e): undefined reference to `log10'    
/usr/local/lib/liblua.a(lmathlib.o): In function `math_pow': lmathlib.c:(.text+0x338): undefined reference to `pow'  
........

2.3 problem 2: The lack of -ldl Parameters ​

/usr/local/lib/liblua.a(loadlib.o): In function `lookforfunc': loadlib.c:(.text+0x748): undefined reference to `dlsym'loadlib.c:(.text+0x7b3): undefined reference to `dlopen'loadlib.c:(.text+0x851): undefined reference to `dlerror'loadlib.c:(.text+0x871): undefined reference to 
`dlerror'/usr/local/lib/liblua.a(loadlib.o): In function `gctm':loadlib.c:
(.text+0xa44): undefined reference to `dlclose'​

Problem analysis ​​

1、 Why does it show up undefined reference to ‘xxxxx’ error ?​

First of all, it's a link error , Not a compilation error , That is to say, if this is the only mistake , Explain that there is no problem with your source code itself , You used the wrong parameters when compiling with the compiler , You didn't specify the library to be used by the linker , For example, some mathematical functions are used in your program , Then you have to specify in the compilation parameters that the program should link to the math library , The method is to add... In the compilation command line -lm.

2、-l Parameters and -L Parameters

-l Parameters It is used to specify the library to which the program will link ,-l The parameter is followed by the library name , So what does a library name have to do with a real library file name ? Take the math library , His library name is m, His library file name is libm.so, It's easy to see , Put the header of the library file name lib And tail .so It's the name of the library . Well, now we know how to get the library name , For example, we need to use a library provided by a third party called libtest.so, So we just need to libtest.so copy to /usr/lib in , Compile with -ltest Parameters , We can use libtest.so The library ( Of course want to use libtest.so Functions in the library , We also need to work with libtest.so Matching header file ). Put it in /lib and /usr/lib and /usr/local/lib The library in the library is used directly -l Parameters will link , But if the library files are not in these three directories , It's in other catalogues , At this time, we only use -l Parameter words , Links still go wrong , The error message is probably :“/usr/bin/ld: cannot find -lxxx”, That's the linker ld There 3 I can't find it in one catalog libxxx.so, Here's another parameter -L That comes in handy , For example, common X11 The library of , It on /usr/X11R6/lib Under the table of contents , We're going to compile with -L/usr/X11R6/lib -lX11 Parameters ,-L The parameter is followed by the name of the directory where the library file is located . Let's take... For example libtest.so Put it in /aaa/bbb/ccc Under the table of contents , The link parameter is -L/aaa/bbb/ccc -ltest in addition , Most of the libxxxx.so It's just a link , With RH9 For example , such as libm.so It links to /lib/libm.so.x,/lib/libm.so.6 And link to /lib/libm-2.3.2.so, If there is no such link , There will still be mistakes , because ld I'll just find libxxxx.so, So if you're going to use xxxx library , And only libxxxx.so.x perhaps libxxxx-x.x.x.so, Just make a link ln -s libxxxx-x.x.x.so libxxxx.so​

Reference material :​
http://blog.csdn.net/uisoul/article/details/60135764
http://blog.csdn.net/uisoul/article/details/60135383
http://blog.csdn.net/uisoul/article/details/60135764

3 How to make Lua call C?( among 3 Ways of planting )

Lua call C, What I've learned is 3 Ways of planting

The way 1. By means of C Register functions in lua call

The way 2. Encapsulated into c Dynamic link library , stay lua in require

The way 3. stay LuaJIT It can be used inside ffi High performance call C( however IOS I don't support LuaJIT..)

3.1 The way 1: stay C Register functions in Lua

lua Provides lua_register Function registration C Function gives lua End calls
hello.c

#include <stdio.h>
#include <string.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
static int l_SayHello(lua_State *L)
{
    
 const char *d = luaL_checkstring(L, 1);// To obtain parameters , String type 
 int len = strlen(d);
 char str[100] = "hello ";
 strcat(str, d);
 lua_pushstring(L, str); /*  Return to lua Value stack of  */
 return 1;
}
int
main(int argc, char *argv[])
{
    
 lua_State *L = luaL_newstate(); /*  establish lua State machine  */
 luaL_openlibs(L); /*  open Lua All in the state machine Lua Standard library  */
 lua_register(L, "SayHello", l_SayHello);// register C Function to lua
 const char* testfunc = "print(SayHello('lijia'))";//lua Call in c function 
 if(luaL_dostring(L, testfunc)) //  perform Lua command .
  printf("Failed to invoke.\n");
 
 /* eliminate Lua*/
 lua_close(L);
 return 0;
}
gcc -o hello hello.c -llua  Compile implementation 

3.2 The way 2: call C Dynamic link library

Create a mylib.c The file of , Then we compile it into a dynamic link library .

#include <stdio.h>
#include <math.h>
#include <stdarg.h>
#include <stdlib.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
/*  All registered to Lua Of C Function has  * "typedef int (*lua_CFunction) (lua_State *L);" The prototype of the . */
static int l_sin(lua_State *L)
{
     
 //  If the element at the index in a given virtual stack can be converted to a number , Returns the converted number , Otherwise, the report will be wrong .
 double d = luaL_checknumber(L, 1);
 lua_pushnumber(L, sin(d)); /* push result */
 
 /*  You can see here ,C You can return to Lua Multiple results , *  Through multiple calls lua_push*(), after return Number of returned results . */
 return 1; /* number of results */
}
/*  Need one "luaL_Reg" Type of structure , Each of these elements corresponds to one provided to Lua Function of . *  Each element contains this function in Lua The name of , And the function in C Function pointers in the library . *  The last element is “ Sentinel element ”( Two "NULL"), Used to tell Lua No other functions need to be registered . */
static const struct luaL_Reg mylib[] = {
    
 {
    "mysin", l_sin},
 {
    NULL, NULL}
};
/*  This function is C In the library “ Special functions ”. *  Register all... By calling it C Functions in the library , And store them in the right place . *  The naming rules for this function should follow : * 1、 Use "luaopen_" As a prefix . * 2、 The name after the prefix will be used as "require" Parameters of . */
extern int luaopen_mylib(lua_State* L)
{
    
 /* void luaL_newlib (lua_State *L, const luaL_Reg l[]); *  Create a new "table", And will "l" The functions listed in are registered as "table" The domain of . */
 luaL_newlib(L, mylib);
 
 return 1;
}

Use gcc -o mylib.so -fPIC -shared mylib.c -llua -ldl Translate it into so
And then create a lua file , Compiled us c Library brought in .

--[[  here "require" The parameter corresponding to C In the library "luaopen_mylib()" Medium "mylib". C The library is right there "a.lua" The same level directory ,"require" Can find .]]
local mylib = require "mylib"
--  The result is the same as in the above example , But here is by calling C The function implementation in the library .
print(mylib.mysin(3.14 / 2)) --> 0.99999968293183

perform a.lua file , Report a mistake later , say Lua There are multiple virtual machines !
lua: multiple Lua VMs detected
 Insert picture description here
Why? ? I checked some data and found that because lua The default compilation is static link library , This will lead to multiple links VM Conflict .
So let's compile another lua The interpreter dynamically links .
mylua.c

#include <stdio.h>
#include "lua.h"
#include "lualib.h"
#include "lauxlib.h"
int main() {
    
 lua_State *L = luaL_newstate();
 luaL_openlibs(L);
if (luaL_loadfile(L, "a.lua") || lua_pcall(L, 0, 0, 0)) {
    
  printf("%s", lua_tostring(L, -1));
 }
}
gcc -o mylua mylua.c -llua -ldl -lm -Wall

So you can compile mylua Executable file
In command line ./mylua perform , Successfully printed out 0.99999968293183

3.3 summary

gcc command , compile lua, compile C Dynamic link libraries have been less exposed before . So I climbed a lot of pits , Ha ha ha . Next, we need to study how to c Parsing binary protocols in lua call , stay c How to package in luatable

Reference material :
https://www.cnblogs.com/pied/archive/2012/10/26/2741601.html
http://blog.csdn.net/vermilliontear/article/details/50947379
http://blog.csdn.net/casularm/article/details/316149
Okay , The above is the whole content of this article , I hope the content of this article has a certain reference value for your study or work , If you have any questions, you can leave a message , Thank you for your support for script house .

原网站

版权声明
本文为[Quiet Zhiyuan 2021]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203020526288297.html