4

これは、1週間以上私を夢中にさせています。以下は、ゲームBitfighterのロボット プレイヤーからの Lua コードの 2 つのスニペットです(バインディングに LuaWrapper のバリアントを使用して C++ で記述されています)。

Lua スクリプトを初めて起動すると、どちらも期待どおりに動作します。しかし、激しいオブジェクトの作成と破棄を数分間行った後、バリアント 2 は動作を停止し、次のエラーが表示されます。

robot.lua:253: attempt to call missing or unknown method 'getEnergy' (a nil value)

私の目には、これらは同じように機能するはずです。誰が違いを説明できますか?

注: ターゲットは、C++ オブジェクトを表す (重い) ユーザーデータです。getEnergy と getHealth は正しく登録された C++ 関数です。この異なる動作を簡単に再現できます。これは luavec mod を使用した Lua 5.1 です。

バリアント 1 - 常に機能します

local mt = getmetatable(target)
local pow = mt.getEnergy(target) + mt.getHealth(target)

バリアント 2 - スクリプトが任意の時間実行された後、失敗し始める

 local pow = target:getEnergy() + target:getHealth()
4

3 に答える 3

1

問題は、次のようなクラスまたは構造体があることだと強く思います。

struct Foo
{
    Bar bar;
    // Other fields follow
}

そして、LuaWrapperを介してFooとBarの両方をLuaに公開したこと。ここで重要なのbarは、構造体の最初のフィールドFooです。または、他の基本クラスから継承するクラスがあり、派生クラスと基本クラスの両方がLuaWrapperに公開されている場合があります。

LuaWrapperは、識別子と呼ばれる関数を使用して、各オブジェクトを一意に追跡します(特定のオブジェクトがすでにLua状態に追加されているかどうかなど)。デフォルトでは、オブジェクトアドレスをキーとして使用します。上記のような場合、FooとBarの両方がメモリ内で同じアドレスを持っている可能性があるため、LuaWrapperが混乱する可能性があります。

これにより、メソッドを検索しようとしたときに、間違ったオブジェクトのメタテーブルを取得する可能性があります。明らかに、間違ったメタテーブルを調べているため、目的のメソッドが見つからないため、メタテーブルのエントリが不思議に失われたように見えます。

1つの巨大な山ではなく、タイプごとに各オブジェクトのデータを追跡する変更をチェックインしました。コピーしたLuaWrapperをリポジトリから最新のものに更新すると、問題が修正されると確信しています。

于 2013-02-23T03:48:07.637 に答える
0

ある段階で動作を停止すると言うと、以前は正常に動作しています...実行時にどこかで.getEnergy関数を上書きした可能性がありますか?多分あなたはどこかのfoo.getEnergy = nil代わりに走っていますか?foo.getEnergy == nil初期化が遅れている可能性があります:)

于 2013-02-02T19:03:17.903 に答える