Lua 作为一个轻量、灵活的嵌入式脚本语言,可供任何需要的程序使用。lua 可利用 C API 方便的嵌入其他系统。
Lua 与 C 交互 通过虚拟栈 栈顶元素索引 -1,栈底元素索引 1
C 调用 Lua a.lua
1 2 3 4 5 6 print("hello from lua") function power(a,n) return a^n end
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 lua_State * L = luaL_newstate(); // 创建 Lua 与 C 进行数据交互的堆栈并返回指针 L; luaL_openlibs(L); //为堆栈加载所有 Lua 的标准库 // 1. 执行 lua 脚本 luaL_dostring(L,"print('from dostring')"); // 2. 执行整个 Lua 脚本文件 a.lua luaL_dofile(L,"a.lua"); // 3. 调用 Lua 中的方法 lua_getglobal(L,"power"); lua_pushinteger(L,2); lua_pushinteger(L,10); lua_call(L,2,1); int res = lua_tonumber(L,-1); // 取出栈顶结果 printf("power:%d",res); lua_close(L); //函数关闭堆栈,释放资源
Lua 调用 C b.lua
1 2 local res = add(20,3) print('res:'..res)
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 //待Lua调用的C注册函数 int add(lua_State* L) { double op1 = lua_tonumber(L,-1); double op2 = lua_tonumber(L,-2); //将函数的结果压入栈中。如果有多个返回值,可以在这里多次压入栈中。 lua_pushnumber(L,op1 + op2); return 1; //返回值表示返回值数量,即压入栈中的返回值数量。 } void lua_call_c() { lua_State *L = luaL_newstate(); luaL_openlibs(L); lua_register(L,"add",add); luaL_dofile(L,"b.lua"); lua_close(L); } int main() { lua_call_c(); return 0; }
Java 与 C 交互 JNI是Java Native Interface的缩写,它提供了若干的API实现了Java和其他语言的通信(主要是C/C++)。
Main.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 package com.jni_java; public class Main { static native int add(int a, int b); static { System.loadLibrary("libjni_c"); } public static void main(String[] args) { System.out.println("hello"); System.out.println("add form c:" + add(2, 3)); } }
main.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 /* * main.c * Author: hanks */ #include <stdio.h> #include "com_jni_java_Main.h" JNIEXPORT jint JNICALL Java_com_jni_1java_Main_add(JNIEnv * env, jclass job, jint n1, jint n2) { // jni diaoyong java jclass clazz = (*env)->FindClass(env, "com/jni_java/BigOp"); if(clazz == NULL){ printf("找不到类"); } jmethodID mid_static_method = (*env)->GetStaticMethodID(env, clazz, "bigNumberAdd", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); if (mid_static_method == NULL) { printf("找不到函数"); } jstring a = (*env)->NewStringUTF(env, "111111111111111111111111111"); jstring b = (*env)->NewStringUTF(env, "22222222222222222222222222"); jobject res = (*env)->CallStaticObjectMethod(env, clazz, mid_static_method, a, b); const char *resultChar = (*env)->GetStringUTFChars(env, res, NULL); printf("bigAdd: %s", resultChar); // 删除引用 (*env)->DeleteLocalRef(env, clazz); (*env)->DeleteLocalRef(env, a); (*env)->DeleteLocalRef(env, b); return n1 + n2; }
Lua 与 Java 交互 实际上也就是 lua <-> c <-> java
, 可以将 lua 编译成对应平台的库 so/dll ,然后嵌入 Java 项目。 介绍一下开源项目 luajava ,该项目实现以下几个方法 借助这几个方法 lua 几乎可以使用所有的 java 类了,参考 luajava.c
newInstance(className, ……) 第一个参数是类名,后面的是构造方法参数
1 local obj = luajava.newInstance("java.lang.Object")
bindClass(className) 这个方法是用来调用类的静态方法的,返回一个java class
1 2 local sys = luajava.bindClass("java.lang.System") print ( sys:currentTimeMillis() )
new(javaClass) 创建一个实例
1 2 local str = luajava.bindClass("java.lang.String") strInstance = luajava.new(str)
createProxy(interfaceNames, luaObject) 这个是使用 java 接口的方法。luaObject 中实现 java 接口中的方法,然后调用 creatProxy 来构建出这个接口的 lua 版本,相当于用 luaObject来实现 java 接口了。
可以多个接口同时调用,然后luaObject实现所有这些接口的方法
1 2 3 4 5 6 7 local button = luajava.newInstance("java.awt.Button", "execute") local buttonProxy = luajava.createProxy("java.awt.ActionListener", { actionPerformed = function(ev) -- body end }) button:addActionListener(buttonProxy)
loadLib(className, methodName) 调研类的静态方法
Lua 与 Android 交互 通过 NDK 编程,编译对应 Android 平台的 so 库,然后调研 Android SDK 来开发 Android
androlua ,改进版本 AndroLua_pro 主要可参考其中 的 import.lua 和 loadlayout.lua ,这两个 lua 文件将如何调用 java 中的类和方法进行优化,使得调用起来非常方便。
相关代码实现 lua_into_android
文章来自: https://hanks.pub