2012-05-31 35 views
5

Gần đây tôi đã được tinkering xung quanh với C# để C + + interop, đặc biệt là thiết lập một chức năng gọi lại được gọi là từ C + + DLL.C# C++ Interop callback

namespace TomCSharpDLLImport 
{ 
    class Program 
    { 
     public delegate void TomDelegate(int a, int b); 

     [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)] 
     public static extern void GetData(); 

     [DllImport("TomDllNative.dll", CallingConvention = CallingConvention.Cdecl)] 
     public static extern void SetCallback(TomDelegate aCallback); 

     static void Main(string[] args) 
     { 
      TomDelegate lTD = new TomDelegate(Program.TomCallback); 

      SetCallback(lTD); //Sets up the callback 

      int thread = Thread.CurrentThread.ManagedThreadId; 

      GetData(); //This calls the callback in unmanaged code 

      while (true) ; 
     } 

     //Callback function which is called from the unmanaged code 
     public static void TomCallback(int a, int b) 
     { 
      Console.WriteLine("A: {0} B: {1}", a, b); 
      int thread = Thread.CurrentThread.ManagedThreadId; 
     } 
    } 
} 

Câu hỏi tôi có là khi kiểm soát chương trình đi vào chức năng TomCallback, tôi đã mong đợi nó sẽ nhấn vào vòng lặp while (true) trong Main. Tuy nhiên thay vào đó chương trình chỉ thoát ra. Tôi hoàn toàn không thể có được đầu của tôi tròn hành vi, một phần của tôi tưởng tượng điều này là như mong đợi nhưng một phần của tôi đã có thể mong đợi nó tiếp tục trong chính.

Những gì tôi đã mong ...

  1. Các GetData() hàm được gọi
  2. Chức năng GetData gọi callback
  3. Chức năng gọi lại trả lại GetData
  4. GetData trả lại main()

Tuy nhiên điều này không đúng.

Ai đó có thể tử tế, đủ để giải thích điều gì xảy ra.

Để tiết kiệm không gian Tôi đã không gửi mã không được quản lý, tuy nhiên nếu nó là cần thiết tôi rất vui khi được gửi

Edit: Tôi bật gỡ lỗi Switch (hoàn toàn quên để làm điều này) và bây giờ tôi thấy sự cố ..

Thời gian chạy kiểm tra thất bại # 0 - Giá trị của ESP không được lưu đúng cách trong một cuộc gọi chức năng. Đây thường là kết quả của việc gọi một hàm được khai báo với một quy ước gọi bằng một con trỏ hàm được khai báo với một quy ước gọi khác.

mã gốc vì đây là nơi vụ tai nạn là

#include "stdafx.h" 
typedef void (*callback_function)(int, int); 

extern "C" __declspec(dllexport) void SetCallback(callback_function aCallback); 
extern "C" __declspec(dllexport) void GetData(); 

callback_function gCBF; 

__declspec(dllexport) void SetCallback(callback_function aCallback) 
{ 
    gCBF = aCallback; 
} 

__declspec(dllexport) void GetData() 
{ 
    gCBF(1, 2); 
} 

Trả lời

11

Bạn phải chuyển đổi callback quản lý của bạn để Pointer Chức năng Native (IntPtr trong C#) bằng cách sử dụng phương pháp

IntPtr Marshal.GetFunctionPointerForDelegate(Delegate d) 

.

Việc bạn sử dụng SetCallback() với System.Delegate làm đối số sai.

Làm cho nó

SetCallback(Marshal.GetFunctionPointerForDelegate(lTD)); 

và redeclare SetCallback như

/// StdCall is crucial here 
[DllImport("TomDllNative.dll", CallingConvention = CallingConvention.StdCall)] 
public static extern void SetCallback(IntPtr aCallback); 
+0

Hi Viktor, Cảm ơn câu trả lời. Tôi đã thực hiện các thay đổi như bạn đã đề xuất, nhưng nó vẫn hiển thị chính xác cùng một hành vi. – TomP89

+0

Chương trình "thoát" - điều này có nghĩa là một sự cố. Bạn có thể loại như vậy để hiển thị đổ rác? Điều này có thể được thực hiện trong công cụ Trình xem sự kiện, trong danh sách Lỗi ứng dụng. Hoặc chỉ copy'n'paste đầu ra bàn điều khiển của chương trình của bạn. –

+0

Cảm ơn Viktor, tôi đã cập nhật câu hỏi – TomP89

Các vấn đề liên quan