Unverwalteter Funktionszeiger __cdecl

Cromon

Erfahrenes Mitglied
Hallo zusammen

Wie der Titel andeutet brauche ich von meinem Delegat einen unverwalteten Funktionszeiger, der der __cdecl Aufrufkonvention genügt. Da mein Code bisher nicht funktioniert und ich keine genauen Angaben habe warum bin ich auf der Suche nach möglichen Fehlern. Mein erster Ansatz war, dass das Delegat, wie in der MSDN beschrieben, in einen __stdcall-Funktionszeiger umgewandelt wurde. Dies sieht folgendermassen aus bisher:
C#:
    public class EventManager
    {
        public EventManager()
        {
            eventHandler = OnEvent;
            LUADelegate.WrapRegisterFunction("theEventHandler", eventHandler);
            mEventScript.Lines.Add("...");

            mEventScript.Execute();
        }

        public int OnEvent(IntPtr state)
        {
            Console.WriteLine("CALLED EVENT!");
            return 0;
        }

        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        delegate int EventDelegate(IntPtr state);

        EventDelegate eventHandler = null;

        LUAScript mEventScript = new LUAScript();
    }


        internal static void WrapRegisterFunction(string function, Delegate pFun)
        {
            Script_RegisterFunction(function, Marshal.GetFunctionPointerForDelegate(pFun));
        }

Ist es korrekt, dass dies einen Funktionszeiger der __cdecl Konvention erstellt?

Besten Dank
Cromon
 
Das Problem hat sich soweit gelöst! Habe zuerst gemerkt, dass ich in meinem LUA-Manager vor dem Aufrufen einer Funktion geprüft habe, ob sie in der .text-Sektion des Hauptmoduls ist und falls nicht eine Exception geworfen habe. Erschien mir damals als eine super Idee, im Nachinein nicht so wirklich. Nachdem ich das geändert hatte habe ich sicherheitshalber mal ein Trampolin erstellt, das die __cdecl-Funktion bereitstellt und dann die __stdcall-Funktion aufruft:
C#:
        internal static IntPtr CreateLuaTrampoline(Delegate pFun)
        {
            IntPtr dest = Marshal.GetFunctionPointerForDelegate(pFun);
            List<byte> code = new List<byte>();
            code.Add(0x55); // push ebp
            code.AddRange(new byte[] { 0x8B, 0xEC }); // mov ebp, esp
            code.AddRange(new byte[] { 0x8B, 0x45, 0x08 }); // mov eax, [ebp + 8]
            code.AddRange(new byte[] { 0x50 }); // push eax
            code.AddRange(new byte[] { 0xB8 }); // mov eax
            code.AddRange(BitConverter.GetBytes(dest.ToInt32())); // pFun
            code.AddRange(new byte[] { 0xFF, 0xD0 }); // call eax
            code.AddRange(new byte[] { 0x8B, 0xE5 }); // mov esp, ebp
            code.AddRange(new byte[] { 0x5D }); // pop ebp
            code.AddRange(new byte[] { 0xC3 }); // retn

            IntPtr pTrampoline = Memory.Native.AllocateCodeMemory(code.Count);
            Memory.Native.Write(code.ToArray(), pTrampoline);

            return pTrampoline;
        }
 
Zurück