首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 與 C++ 互操作:正確處理回調函數中的字符串指針

     編輯:關於C語言

問題核心

C++ 回調簽名:typedef void (*TDataEvent)(char *AData, int ALen);

  • AData:C++ DLL 內部分配內存的字符串指針
  • ALen:數據長度

C# 直接用 byte[] 接收會導致數據截斷(僅收到第一字節),因為默認封送無法正確處理非托管指針。

錯誤示範

// 錯誤:byte[] 默認封送為 In/Out 參數,不匹配 char*
public delegate void TDataEvent(byte[] AData, int ALen);

public void getDate(byte[] AData, int ALen)
{
    // AData.Length 永遠為 1,數據丟失
}

正確解決方案:IntPtr + 手動封送

using System;
using System.Runtime.InteropServices;

public delegate void TDataEvent(IntPtr pData, int len); // 1. 用 IntPtr 接收指針

public class CppInterop
{
    // 2. 保持委托實例存活,防止 GC 回收
    private TDataEvent _callbackInstance; 

    public void RegisterCallback()
    {
        _callbackInstance = new TDataEvent(OnDataReceived);
        // 假設 ReceDllPoxy.AddServer 是導入的 C++ 函數
        ReceDllPoxy.AddServer(1024, _callbackInstance, 2);
    }

    private void OnDataReceived(IntPtr pData, int len)
    {
        if (pData == IntPtr.Zero || len <= 0) return;

        // 3. 正確複製非托管內存到托管字節數組
        byte[] managedData = new byte[len];
        Marshal.Copy(pData, managedData, 0, len);

        // 4. 按編碼轉字符串(視 C++ 實際編碼而定)
        string str = System.Text.Encoding.Default.GetString(managedData);
        // 或 UTF8: Encoding.UTF8.GetString(managedData)
        
        Console.WriteLine($\"收到數據 ({len} 字節): {str}\");
        
        // 注意:內存由 C++ 端管理,C# 端不應釋放
    }
}

// C++ DLL 導入簽名示例
internal static class ReceDllPoxy
{
    [DllImport(\"YourCppDll.dll\", CallingConvention = CallingConvention.Cdecl)]
    public static extern void AddServer(int port, TDataEvent callback, int flag);
}

關鍵點總結

問題解決方案
byte[] 只收到 1 字節改用 IntPtr 接收原始指針
委托被 GC 回收將委托實例存為類成員變量
非托管內存複製Marshal.Copy(ptr, byte[], 0, len)
編碼不匹配確認 C++ 端編碼(ANSI/UTF-8),對應選擇 Encoding
調用約定C++ 默認 __cdecl,C# 需指定 CallingConvention.Cdecl

進階:動態加載 DLL 通用封裝

文中提供的 clDllBasePoxy / clDllPoxy 展示了通過 LoadLibrary / GetProcAddress / Marshal.GetDelegateForFunctionPointer 實現運行時動態綁定非托管 DLL 的完整框架,適合插件化架構。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved