2010-06-04 17 views
23

¿Cómo paso un puntero de función desde C++ administrado (C++/CLI) a un método no administrado? Leí algunos artículos, como this one from MSDN, pero describe dos conjuntos diferentes, mientras que solo quiero uno.C++/cli pass (administrado) delegado al código no administrado

Aquí está mi código:

1) Cabecera (MyInterop.ManagedCppLib.h):

#pragma once 

using namespace System; 

namespace MyInterop { namespace ManagedCppLib { 

    public ref class MyManagedClass 
    { 
    public: 
     void DoSomething(); 
    }; 
}} 

2) CPP Código (MyInterop.ManagedCppLib.cpp)

#include "stdafx.h" 
#include "MyInterop.ManagedCppLib.h" 

#pragma unmanaged 
void UnmanagedMethod(int a, int b, void (*sum)(const int)) 
{ 
    int result = a + b; 
    sum(result); 
} 

#pragma managed 
void MyInterop::ManagedCppLib::MyManagedClass::DoSomething() 
{ 
    System::Console::WriteLine("hello from managed C++"); 
    UnmanagedMethod(3, 7, /* ANY IDEA??? */); 
} 

I intenté crear mi delegado administrado y luego traté de usar el método Marshal::GetFunctionPointerForDelegate, pero no pude compilar.

+0

¿Podría publicar el código, en el que utilizó GetFunctionPointerForDelegate? – Simon

Respuesta

37

Sí, quiere Marshal :: GetFunctionPointerForDelegate(). Al fragmento de código le falta la función administrada a la que desea llamar, acabo de crear una. También deberá declarar el tipo de delegado administrado y crear una instancia del mismo antes de que pueda obtener un puntero a la función. Esto funcionó bien:

#include "stdafx.h" 

using namespace System; 
using namespace System::Runtime::InteropServices; 

#pragma managed(push, off) 
typedef void (* UnmanagedSummer)(int arg); 

void UnmanagedMethod(int a, int b, UnmanagedSummer sum) 
{ 
    int result = a + b; 
    sum(result); 
} 
#pragma managed(pop) 

ref class Test { 
    delegate void ManagedSummer(int arg); 
public: 
    static void Run() { 
     Test^ t = gcnew Test(); 
     ManagedSummer^ managed = gcnew ManagedSummer(t, &Sum); 
     IntPtr stubPointer = Marshal::GetFunctionPointerForDelegate(managed); 
     UnmanagedSummer functionPointer = static_cast<UnmanagedSummer>(stubPointer.ToPointer()); 
     UnmanagedMethod(1, 2, functionPointer); 
     GC::KeepAlive(managed); // Important: ensure stub can't be collected while native code is running 
     System::Diagnostics::Debug::Assert(t->summed == 3); 
    } 
    void Sum(int arg) { 
     summed += arg; 
    } 
    int summed; 
}; 

int main(array<System::String ^> ^args) 
{ 
    Test::Run(); 
    return 0; 
} 
+0

Este casting extra fue el "eslabón perdido" :-) ¡Gracias! –

Cuestiones relacionadas