返回「计算机、信息技术与工程」
Cocos2dx binding
本文目录 5 个章节
Cocos2dx binding
# Cocos2dx binding
JSB
// MyApiJSB.cpp
#include "scripting/js-bindings/manual/ScriptingCore.h"
#include "MyApi.h"
static bool js_myapi_echo(JSContext* cx, uint32_t argc, jsval* vp) {
if (argc == 1) {
JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
std::string s;
if (args.get(0).isString()) {
JS::RootedString rs(cx, args.get(0).toString());
s = JS_EncodeStringToUTF8(cx, rs);
} else return false;
auto out = MyApi::echo(s);
JS::RootedString jsOut(cx, JS_NewStringCopyZ(cx, out.c_str()));
args.rval().set(STRING_TO_JSVAL(jsOut));
return true;
}
return false;
}
static void bind_myapi(JSContext* cx, JS::HandleObject global) {
static JSFunctionSpec specs[] = {
JS_FN("echo", js_myapi_echo, 1, JSPROP_PERMANENT | JSPROP_ENUMERATE),
JS_FS_END
};
JS::RootedObject ns(cx, JS_NewObject(cx, nullptr, JS::NullPtr(), JS::NullPtr()));
JS::RootedValue v(cx, OBJECT_TO_JSVAL(ns));
JS_SetProperty(cx, global, "myapi", v);
JS_DefineFunctions(cx, ns, specs);
}
// somewhere in startup (e.g., AppDelegate)
auto se = ScriptingCore::getInstance();
if (auto cx = se->getGlobalContext()) {
JS::RootedObject g(cx, se->getGlobalObject());
bind_myapi(cx, g);
} else {
se->addRegisterCallback(bind_myapi);
}
JS 端即可:
myapi.echo("hello"); // -> "hello"
Lua
1) 最小可用 C++ 代码(MyLuaBindings.cpp)
// MyLuaBindings.cpp —— 加入到你的原生工程参与编译
#include "cocos2d.h"
#include "scripting/lua-bindings/manual/CCLuaEngine.h"
#include "tolua++.h" // 若报未定义的 tolua_*,补这个头
using namespace cocos2d;
#define MY_LUA_NS "myapi" // Lua 侧的命名空间:myapi.xxx
// —— 示例的原生状态(仅演示)——
namespace MyNative {
static int value = 0;
static void setValue(int v) { value = v; }
static int getValue() { return value; }
static std::string greet(const char* name) {
return std::string("Hello, ") + (name ? name : "");
}
}
// 1) 绑定函数:入参校验 + 业务调用 + 压回返回值数量
// myapi.setValue(number)
static int lua_myapi_setValue(lua_State* L) {
int argc = lua_gettop(L);
if (argc != 1 || !lua_isnumber(L, 1)) {
CCLOGERROR("myapi.setValue(number) expects 1 number");
return 0;
}
MyNative::setValue((int)lua_tointeger(L, 1));
return 0; // 返回 0 个值
}
// local v = myapi.getValue()
static int lua_myapi_getValue(lua_State* L) {
lua_pushinteger(L, MyNative::getValue());
return 1; // 返回 1 个值
}
// local s = myapi.greet("Cocos")
static int lua_myapi_greet(lua_State* L) {
const char* name = luaL_checkstring(L, 1); // 不符会抛 Lua 错误
std::string s = MyNative::greet(name);
lua_pushlstring(L, s.c_str(), s.size());
return 1;
}
// 2) 把函数注册进 Lua 命名空间:myapi
static void bindMyLuaFunctions(lua_State* L) {
if (!L) { CCLOGERROR("bindMyLuaFunctions: null lua_State"); return; }
lua_getglobal(L, "_G"); // stack: ... _G
if (lua_istable(L, -1)) {
tolua_open(L);
tolua_module(L, MY_LUA_NS, 0);
tolua_beginmodule(L, MY_LUA_NS);
tolua_function(L, "setValue", lua_myapi_setValue);
tolua_function(L, "getValue", lua_myapi_getValue);
tolua_function(L, "greet", lua_myapi_greet);
tolua_endmodule(L);
}
lua_pop(L, 1); // pop _G
}
// 3) 对外导出一个“注册入口”,在启动时调用一次
void registerMyLuaBindings() {
auto engine = LuaEngine::getInstance();
if (!engine) { CCLOGERROR("LuaEngine not found"); return; }
bindMyLuaFunctions(engine->getLuaStack()->getLuaState());
}
2) 在启动流程里调用一次
// AppDelegate.cpp
bool AppDelegate::applicationDidFinishLaunching() {
// ... 你的初始化 ...
registerMyLuaBindings(); // ★ 注册 Lua 绑定
// ... 继续加载 Lua 脚本等 ...
return true;
}
3) Lua 侧用法示例
myapi.setValue(42)
print("value =", myapi.getValue()) -- 42
print(myapi.greet("Cocos")) -- "Hello, Cocos"