Делегат C ++ / CLI как указатель на функцию (System.AccessViolationException)

Я экспериментировал с делегатами C ++ / CLI (так как я пытался создать справочную библиотеку .NET), и у меня возникла следующая проблема .

Я определяю делегат в C ++ / CLI, а затем создаю экземпляр делегата в C #, а затем вызываю экземпляр делегата через неуправляемый C ++ через указатель на функцию. Все работает так, как ожидалось.

Код, иллюстрирующий это (сначала мой C #)

using System;

namespace TestProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            Library.Test.MessageDelegate messageDelegate = new Library.Test.MessageDelegate(Message);
            Library.Test test = new Library.Test(messageDelegate);
            test.WriteMessage();
            Console.Read();
        }

        static void Message()
        {
            Console.WriteLine(1024);
        }
    }
}

Затем мой управляемый файл C ++ (Managed.cpp)

#include "Unmanaged.hpp"
#include <string>

namespace Library
{
    using namespace System;
    using namespace System::Runtime::InteropServices;

    public ref class Test
    {
    public:
        delegate void MessageDelegate();
    internal:
        MessageDelegate^ Message;
        void* delegatePointer;

    public:
        Test(MessageDelegate^ messageDelegate)
        {
            delegatePointer = (void*)Marshal::GetFunctionPointerForDelegate(messageDelegate).ToPointer();
        }

        void WriteMessage()
        {
            Unmanaged::WriteMessage(delegatePointer);
        }
    };
}

И мой неуправляемый файл C ++ (Unmanaged.cpp)

#include "Unmanaged.hpp"

namespace Unmanaged
{
    typedef void (*WriteMessageType)();
    WriteMessageType WriteMessageFunc;

    void WriteMessage(void* Function)
    {
        WriteMessageType WriteMessageFunc = (WriteMessageType)(Function);
        WriteMessageFunc();
    }
}

Весь этот код работает, как ожидалось, и на выходе получается «1024», так как Method () вызывается указателем функции на метод делегата.

Моя проблема возникает при попытке применить тот же метод к делегату с аргументами, а именно: delegate void MessageDelegate (int number);

Мой код теперь выглядит следующим образом (C #):

using System;

namespace AddProgram
{
    class Program
    {
        static void Main(string[] args)
        {
            Library.Test.MessageDelegate messageDelegate = new Library.Test.MessageDelegate(Message);
            Library.Test test = new Library.Test(messageDelegate);
            test.WriteMessage(1024);
            Console.Read();
        }

        static void Message(int number)
        {
            Console.WriteLine(number);
        }
    }
}

Мой управляемый файл C ++ :

#include "Unmanaged.hpp"
#include <string>

namespace Library
{
    using namespace System;
    using namespace System::Runtime::InteropServices;

    public ref class Test
    {
    public:
        delegate void MessageDelegate(int number);
    internal:
        MessageDelegate^ Message;
        void* delegatePointer;

    public:
        Test(MessageDelegate^ messageDelegate)
        {
            delegatePointer = (void*)Marshal::GetFunctionPointerForDelegate(messageDelegate).ToPointer();
        }

        void WriteMessage(int number)
        {
            Unmanaged::WriteMessage(delegatePointer, number);
        }
    };
}

И мой неуправляемый файл C ++:

#include "Unmanaged.hpp"

namespace Unmanaged
{
    typedef void (*WriteMessageType)(int number);
    WriteMessageType WriteMessageFunc;

    void WriteMessage(void* Function, int number)
    {
        WriteMessageType WriteMessageFunc = (WriteMessageType)(Function);
        WriteMessageFunc(number);
    }
}

Когда я запускаю программу, я получаю следующую ошибку:

Необработанное исключение типа 'System.AccessViolationException' произошло в Unmanaged Library Test.dll

Дополнительная информация: Попытка прочитать или записать в защищенную память. Это часто указывает на то, что другая память повреждена.

Между прочим, в окне консоли действительно отображается 1024, но затем следует случайное целое число (~ 1000000), а затем я получаю сообщение об ошибке.

Я могу представить себе некоторые из причин, по которым я получаю эту ошибку, но я не уверен и затрудняюсь выяснить. Если бы кто-нибудь мог сказать мне, почему я получаю эту ошибку, и что я могу сделать, чтобы ее исправить, я был бы очень признателен.

18
задан xcvd 30 December 2011 в 02:44
поделиться