Обратный вызов неуправляемого кода из управляемого C # - PullRequest
1 голос
/ 26 июня 2009

Немного урока истории здесь. Я работаю над унаследованным приложением C ++ / MFC и пытаюсь начать постепенную модернизацию, выдвигая компоненты, написанные на C # (WinForms и более поздние WPF).

Я застрял с использованием .Net / 1.1 и VS / 2003 по многим причинам, которые невозможно решить в ближайшем будущем.

В настоящее время в качестве доказательства концепции работает нечто подобное:

#pragma push_macro("new")
#undef new

WinFormA::Form1* myform;
myform = __gc new WinFormA::Form1();
myform->ShowDialog();

#pragma pop_macro("new")

Проблема, с которой я столкнулся, заключается в следующем: мне нужен неуправляемый код C ++ / MFC для передачи указателя обратного вызова в управляемый код C # WinForm, чтобы я мог фиксировать взаимодействия с пользователем и обрабатывать их в приложении.

Я просматривал некоторые статьи, например в этой статье MSDN , но он не работает в VS / 2003 (компилятору не нравится синтаксис делегата).

Есть ли другие варианты? Я не думаю, что могу использовать DLLImport, поскольку мне нужно взаимодействовать с конкретным экземпляром приложения, а не с плоским API.

Спасибо!

Ответы [ 3 ]

1 голос
/ 23 сентября 2009

Если другие ответы не сработают, вы всегда можете написать оболочку C, чтобы сгладить классы. Например, если класс C ++ имеет вид:

class TheClass {
  public:
    TheClass(int Param);
    ~TheClass();

    bool SomeFunction(int Param1,int Param2);
};

Я напишу обертку:

extern "C" void *TheClass_Create(int Param) {
  return (void*) new TheClass(Param);
}

extern "C" void TheClass_Destroy(void *This) {
  delete (TheClass*) This;
}

extern "C" bool TheClass_SomeFunction(void *This,int Param1,int Param2) {
  return ((TheClass*) This)->SomeFunction(Param1,Param2);
}

Поскольку оболочка является прямой C, вы можете P / Invoke в C # на свое усмотрение ( void *. Этот должен стать IntPtr для обеспечения совместимости, если вы перейдете на 64-битную версию). Иногда, если я действительно честолюбив, я пишу обертку C # вокруг P / Вызывает, чтобы «переклассифицировать» вещь.

0 голосов
/ 26 июня 2009

Я никогда не пробовал сам, но вы проверяли структуру RuntimeMethodHandle, которая определенно существует в .net1?

SomeDelegate Handler = new SomeDelegate(SomeMethod);
IntPtr HandlerPtr = Handler.Method.MethodHandle.GetFunctionPointer();

И несколько копий-вставок из описания MSDN .net2 Marshal :: GetDelegateForFunctionPointer Метод:

В версиях 1.0 и 1.1 .NET Framework можно было передавать делегат, представляющий управляемый метод, в неуправляемый код в качестве указателя на функцию, позволяя неуправляемому коду вызывать управляемый метод через указатель на функцию. Неуправляемый код также мог передать указатель этой функции обратно в управляемый код, и указатель был правильно преобразован в базовый управляемый метод.

0 голосов
/ 26 июня 2009

Я уже забыл .NET 1. *, но:

Определите необходимые интерфейсы и зарегистрируйте ваши компоненты .NET как COM-объекты. Утилиты .NET обычно предоставляют достаточно хороший код маршалинга.

Если возможно, обращайтесь к ним как к COM-объектам из приложения C ++ без какого-либо управляемого C ++. (Используйте указатели интерфейса вместо функций для обратных вызовов).

Если COM не вариант, используйте .NET Reflector, чтобы увидеть, что происходит внутри автоматически созданных сборок взаимодействия - это может дать представление о том, как сделать то же самое вручную.

...