2010-06-04 5 views
23

Comment passer un pointeur de fonction de C++ géré (C++/CLI) à une méthode non managée? J'ai lu quelques articles, comme this one from MSDN, mais il décrit deux assemblées différentes, alors que je n'en veux qu'une.C++/passe cli (géré) délégué au code non managé

Voici mon code:

1) En-tête (MyInterop.ManagedCppLib.h):

#pragma once 

using namespace System; 

namespace MyInterop { namespace ManagedCppLib { 

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

2) Code du RPC (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 J'ai essayé de créer mon délégué géré, puis j'ai essayé d'utiliser la méthode Marshal::GetFunctionPointerForDelegate, mais je n'ai pas pu compiler.

+0

Pourriez-vous s'il vous plaît poster le code, dans lequel vous avez utilisé GetFunctionPointerForDelegate? – Simon

Répondre

37

Oui, vous voulez Marshal :: GetFunctionPointerForDelegate(). Votre extrait de code manque de la fonction gérée que vous souhaitez appeler, je viens d'en créer un. Vous devrez également déclarer le type de délégué géré et en créer une instance avant de pouvoir obtenir un pointeur de fonction. Cela a bien fonctionné:

#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

Ce casting supplémentaire était le "chaînon manquant" :-) Merci! –

Questions connexes