11

Lua 5.2 用の Lua-C API を使用して、Lua で C 関数をラップしています。

#include <lua.h>
#include <lauxlib.h>
#include <stdlib.h>
#include <stdio.h>

int foo_gc();
int foo_index();
int foo_newindex();
int foo_dosomething();
int foo_new();

struct foo {
  int x;
};

static const luaL_Reg _meta[] = {
    {"__gc", foo_gc},
    {"__index", foo_index},
    {"__newindex", foo_newindex},
    { NULL, NULL }
};
static const luaL_Reg _methods[] = {
    {"new", foo_new},
    {"dosomething", foo_dosomething},
    { NULL, NULL }
};

int foo_gc(lua_State* L) {
  printf("## __gc\n");
  return 0;
}
int foo_newindex(lua_State* L) {
  printf("## __newindex\n");
  return 0;
}
int foo_index(lua_State* L) {
  printf("## __index\n");
  return 0;
}
int foo_dosomething(lua_State* L) {
  printf("## dosomething\n");
  return 0;
}
int foo_new(lua_State* L) {
  printf("## new\n");

  lua_newuserdata(L,sizeof(Foo));
  luaL_getmetatable(L, "Foo");
    lua_setmetatable(L, -2); 

  return 1;
}

void register_foo_class(lua_State* L) {
    luaL_newlib(L, _methods); 
  luaL_newmetatable(L, "Foo");
  luaL_setfuncs(L, _meta, 0);
  lua_setmetatable(L, -2);
  lua_setglobal(L, "Foo");
}

この Lua を実行すると:

local foo = Foo.new()
foo:dosomething()

...次の出力が表示されます (エラーあり):

## new
## __index
Failed to run script: script.lua:2: attempt to call method 'dosomething' (a nil value)

私は何を間違っていますか?

4

3 に答える 3

11

わかりました、うまくいきました。以下に示すように、 と の新しいメタテーブル__indexを追加する必要があり__metatableました。Foo

void register_foo_class(lua_State* L) {
  int lib_id, meta_id;

  /* newclass = {} */
  lua_createtable(L, 0, 0);
  lib_id = lua_gettop(L);

  /* metatable = {} */
  luaL_newmetatable(L, "Foo");
  meta_id = lua_gettop(L);
  luaL_setfuncs(L, _meta, 0);

  /* metatable.__index = _methods */
  luaL_newlib(L, _methods);
  lua_setfield(L, meta_id, "__index");  

  /* metatable.__metatable = _meta */
  luaL_newlib(L, _meta);
  lua_setfield(L, meta_id, "__metatable");

  /* class.__metatable = metatable */
  lua_setmetatable(L, lib_id);

  /* _G["Foo"] = newclass */
  lua_setglobal(L, "Foo");
}
于 2012-06-25T20:57:57.003 に答える
4

私はあなたの解決策に返信しようとしましたが、どうやらまだそうする評判がないようですので、ここに別の回答があります.

あなたのソリューションはかなりいいですが、私がやりたいことはできません。オブジェクトへの「配列のような」アクセスと、まだ関数があります。このLuaコードを見てください:

Foo = {}

mt = {
__index = function(table, key)
  print("Accessing array index ", tostring(key), "\n")
  return 42
end
}
setmetatable(Foo, mt)

Foo.bar = function()
  return 43
end

print(tostring(Foo[13]), "\n")
print(tostring(Foo.bar()), "\n")

--[[
Output:
Accessing array index 13
42
43
]]--

__indexエントリが上書きされるため、ソリューションを使用してクラスを登録すると、これが許可されないようです。クラスで配列アクセスと関数アクセスの両方を使用するのは意味がないかもしれませんが、簡単にするために (両方のタイプのクラスを登録するための 1 つの C 関数を提供する)、どこでも同じコードを使用したいと考えています。関数 Foo.bar() と Foo[13] の両方を持つ C からクラスを作成できるように、この制限を回避する方法を知っている人はいますか?

于 2012-07-17T00:40:23.343 に答える