2017-09-13 4 views
0

이 문제는 베어 본으로 잘라 냈습니다. 제 3 자 시장 데이터 DLL을 사용하고 있으며이 연결은 CManager 클래스에서 관리합니다. 이것은 다음과 같이 CManagerWrapper 클래스로 래핑됩니다.C++/CLI - C#의 콜백

// clr.cpp 

    #include <windows.h> 
    #using <System.dll> 

    using namespace System; 

    class CManager 
    { 
    public: 
     CManager() {} 
     ~CManager() {} 
    }; 

    public ref class CManagerWrapper { 
    public: 
     CManagerWrapper() : m_Impl(new CManager) {} 
     ~CManagerWrapper() { 
      delete m_Impl; 
     } 

    public: 
     typedef void(__stdcall *Callbackfunc)(int); 
     void TestCallBack(Callbackfunc cbf) 
     { 
      cbf(2); 
     } 

    private: 
     CManager * m_Impl; 
    }; 

C++ 프로그램은 DLL (CLR 콘솔 응용 프로그램)로 컴파일되고 다음 C# 프로젝트에서 참조됩니다. 처음 자상는 관리 클래스를 통해 콜백 함수에 대한 포인터를 얻을 수 있었다, 그래서

using System; 
using System.Runtime.InteropServices; 

namespace main 
{ 
    class Program 
    { 

     [UnmanagedFunctionPointer(CallingConvention.StdCall)] 
     delegate void CallbackFunc(int value); 

     static void Main(string[] args) 
     { 

      CallbackFunc callback = 
       (value) => 
       { 
        Console.WriteLine("Callback value = {0}", value); 
       }; 

      CManagerWrapper mw = new CManagerWrapper(); 

      mw.TestCallBack(Marshal.GetFunctionPointerForDelegate(callback)); 

     } 
    } 
} 

좀 콜백을 관리해야합니다. 문제는 클래스의 TestCallBack() 메서드를 인식하지 못하는 C# 측에 있습니다. 그것은 단순히 그것을 볼 수 없습니다. 간단한 인자로 다른 메소드를 만들면 함수 포인터 인자로 인해이 함수가 마음에 들지 않습니다.

error CS0570: 'CManagerWrapper.TestCallBack(?)' is not supported by the language 

누군가 내가 무슨 짓을하고 있는지 말해 줄 수 있습니까? 아마 C++과 C# 사이에 레이어가 필요할 것입니다.

+0

당신이 간단한 'delegate' 또는'의회 처리를 사용할 수있는'ref' 클래스이기 때문에? –

+0

이런 종류의 NET 포장은 나에게 모두 새로운 것입니다. 그게 어떻게 효과가 있는지 말해 줄 수 있어요? –

+0

가능한 대답은 Callbackfunc가 함수가 아니라 대리자로 선언되어야한다는 것입니다. [ointer : https://stackoverflow.com/questions/26547215/how-to-pass-c-sharp-method-as-a-callback-to -cli-c-function – PaulF

답변

0

C++/cli를 사용하고 있으므로 모든 .NET (및 관리되는) 코드 기능을 사용할 수 있습니다. 예 : 네이티브 함수 포인터 대신 Action 또는 Delegate을 사용합니다.

코드 예 :

testclass.h 파일 alibrary (.DLL) 등

#pragma once 

#using <System.dll> 

using namespace System; 

class NativeClass 
{ 
public: 
    NativeClass(); 
    ~NativeClass(); 
}; 
namespace Managed 
{ 
    // delegate declaration as in simple C# code 
    public delegate void ManagedCallbackHandler(int); 

    public ref class ManagedClass 
    { 
    public: 
     ManagedClass(); 
     ~ManagedClass(); 

     // call this directly from c# with method adequate to the action 
     void TestCallBack(Action<int>^); 
     // call this directly from C# with method adequate to the handler 
     void TestCallBack2(ManagedCallbackHandler^); 

    private: 
     NativeClass * m_native; 
    }; 
} 

testclass.cpp 파일

#include "TestClass.h" 

NativeClass::NativeClass() { } 
NativeClass::~NativeClass() { } 

Managed::ManagedClass::ManagedClass() : m_native(new NativeClass) { } 
Managed::ManagedClass::~ManagedClass() { delete m_native; } 

void Managed::ManagedClass::TestCallBack(System::Action<int>^ cbf) 
{ 
    cbf(2); 
} 

void Managed::ManagedClass::TestCallBack2(Managed::ManagedCallbackHandler^ cbf) 
{ 
    cbf(2); 
} 

빌드이 그것을 참조 C# 응용 프로그램에서. 그럼 그냥 단순히이 사용

class Program 
{ 
    static void Main(string[] args) 
    { 
     Managed.ManagedClass c = new Managed.ManagedClass(); 
     // call using Action<int> 
     c.TestCallBack(Console.WriteLine); 
     // call using ManagedCallbackHandler 
     c.TestCallBack2(Console.WriteLine); 
     Console.ReadLine(); 
    } 
} 
+0

감사합니다 m.rogalski - 이것은 금 먼지입니다! 커스텀 함수로 TestCallBack2()를 테스트했는데 정상적으로 작동했습니다. 다음으로해야 할 일은 네이티브 C++ 클래스에 콜백 함수를 전달하는 것입니다. 나는 함수 포인터를 꼭 사용해야 할 것입니다. 맞습니까? 관리되는 클래스에서 Marshal.GetFunctionPointerForDelegate()를 사용하여 전달합니다. –