Schnittstelle LuaEngine und Application

08/04/2008 19:19 Term!nX#1
Ahoi,

Jo hab jetzt 6 Stunden lang auf meine Tasta eingehackt und lief auch alles glatt, nur die Hauptsache, wo ich anfangs dachte "kein Problem", läuft kurz um gar nicht :D

Und zwar gibts einmal Klasse A, die Luaengine, bei der uA Macrofunktionen registriert sind..

.. und Klasse B in der die Spieldaten gesammelt werden. Diese Klasse enthält Funktionen, die diese Daten zurückgeben. Diese Funktionen sind bei der Engine registriert, damit der User diese Spieldaten in seinem Script benutzen kann.


Das Problem ist, dass diese Funktionen beim Aufruf durch die Engine immer den festgelegten Standartwert von 0 zurückgeben.
Es gibt also 2 Arten von Variablen der Dataklasse (sozusagen). Die richtigen, mit denen auch die GUI arbeitet, die auch die richtigen Werte anzeigt und die falschen, mit denen die Engine hantiert.

Ich habe leider nicht die leiseste Ahnung, wo das Problem liegt.

Set Data:
Code:
        GameData gd = new GameData();

        public void _SetData()
        {
            Thread t = new Thread(new ThreadStart(SetData));
            t.IsBackground = true;
            t.Start();
        }

        public void SetData()
        {
            IntPtr handle = OpenProcess(0x0008 | 0x0010 | 0x0020, false, (uint)Id);

            if (handle == null)
            {
                MessageBox.Show("Error when creating processhandle.", "Error!");
                return;
            }

            UIntPtr SizeInt = (UIntPtr)sizeof(int);
            UIntPtr SizeFloat = (UIntPtr)sizeof(float);

            IntPtr bw;

            bool success;

            byte[] buffer = new byte[4];

            while (true)
            {
                success = ReadProcessMemory(handle, PlayerXa, buffer, SizeFloat, out bw);
                if (!success)
                {
                    int error = Marshal.GetLastWin32Error();
                    MessageBox.Show("Error while getting GameData. Errorcode: " + error.ToString(), "Error!");
                }
                float PX = BitConverter.ToSingle(buffer, 0);
                this.Playerx = PX;
                gd.Playerx = PX;
                MessageBox.Show(gd.Playerx.ToString());

/* hier lass ich mir mal den Wert anzeigen. Der Wert stimmt. */

                buffer = new byte[4];

           
                Thread.Sleep(150);
            }


/* für das PropertyGrid */
        public float PlayerPosX
        {
            get { return Playerx; }
            set { }
        }
Set Data wird über den GUIthread aufgerufen.

Auszug der GameData class:

Code:
        public float Playerx;

        public float PlayerX()
        {
            return Playerx;
        }
/* gibt den Wert von Playerx zurück. Playerx wird im SetData Thread durch den ausgelesenen Wert definiert. 
*/
Die Lua-Klasse

Code:
        Lua pLuaVM = new Lua();
        
        private Thread LuaThread;

        public void Register()
        {

            GameData data = new GameData();

            pLuaVM.RegisterFunction("PlayerX", data, data.GetType().GetMethod("PlayerX"));

        }

/* diese Registerfunktion wird beim Start der Applikation aufgerufen */

/* über den Run-Button wird dann die Scriptexecution ausgelöst: */

        public void Main()
        {
            LuaThread = new Thread(new ThreadStart(LuaRun));
            LuaThread.IsBackground = true;
            LuaThread.Start();
        }

        public void LuaRun()
        {
            try
            {
                this.running = 1; /*running flag wird auf normal laufend gesetzt*/
                pLuaVM.DoString(this.script); /* Methode, die die LUAvm einen String abarbeiten lässt*/
            }

            catch (ThreadAbortException ex)
            {

            }

            catch (Exception ex)
            {
                MessageBox.Show("Error: " + ex.Message, "Error!");
            }
        }
Wenn ich jetzt die PlayerX() Funktion aufrufe, um den Wert von PlayerX aus der GameData Klasse an die Engine zu liefern, dann wird immer der Standartwert von 0 zurückgegeben, als wenn das Objekt gerade instanziert würde. Da ich aber zu Testzwecken in den Konstruktor eine MsgBox getan habe, konnte ich feststellen, dass GameData nicht initialisiert wird.

Hlep plx, da ich nicht den geringsten Schimmer habe ..

Grüße
08/04/2008 23:37 mondesser#2
hmm spontan sehe ich keinen fehler. Außer vielleicht locking probleme. du greifst aus verschiedenen threads auf PX zu. Also sollte ein Lock davor.
Ich schau morgen nochmal in ruhe, bin geringfügig betrunken atm xD

edit: ist float ein referenz typ oder ein wert typ? bin mir gerade nicht sicher. Da könnte vllt. noch ein problem liegen. Wobei eigentlich nicht, der GC räumt ja nix weg solange irgendwo noch eine ref existiert.
08/05/2008 12:31 Term!nX#3
Die Gamedata klasse hab ich jetzt aufgelöst und die ganzen Daten/Funktionen in die Dataklasse gepackt. Was ich mir da gedacht hab, hat nicht funktioniert.

So das Problem hab ich jetzt wenigstens lokalisieren können (denk ich zumindest :P) und zwar habe ich mir mal bei LuaRun Methode den Wert von Data.Playerx anzeigen lassen und der ist auch 0. Irgendwie muss der Thread in dem die Engine läuft nicht an die korrekten Daten kommen. Was ich vermute ist, dass nur in dem SetData-Thread die richtigen Werte existieren. In allen anderen Threads existieren die Standartwerte.
08/06/2008 11:49 verT!c4L#4
Quote:
Originally Posted by Term!nX View Post
Code:
        private Thread LuaThread;
Muss das so sein ? o.O
08/06/2008 16:45 Term!nX#5
Ich hab keine Ahnung, das sind teilweise Codestücke die ich aus älteren Projekten übernommen habe. Aber ich brauche das Threadobjekt, wie soll ich sagen, global, damit die LuaAbort Methode geht. Wenn du das private meinst, hielt ich für sinnvoll, da eigentlich kein Zugriff von außen auf den Thread nötig ist. Der LuaThread nimmt ja sozusagen nur.
08/06/2008 20:31 mondesser#6
Hat es irgendeinen Grund, dass du selber Thread objecte erstellst?
Du könntest den wesentlich komfortableren ThreadPool benutzen.
Oder einen BackgroundWorker.
08/07/2008 16:02 Term!nX#7
Mit Threadobjekten habe ich immer backgroundworker gemacht. Kann ich ja mal auf andere Weise probieren.