C#调用C++DLL 获取的结构体里 char[] 乱码

2019年的4月23号  今天天气 没有了前几天的惠风和畅  但仍是天朗气清 

 来邦对讲SDK二次开发SDK文档如下:

1. 数据存放的所需结构体(对讲设备出现呼叫挂断等动作时,回调函数所需)

2. 32位C++方法(32位还是64位提前确认)

 //用来初始化SDK类库

  //用来注册回调函数

 //具体回调函数内容

C#二次调用开发:

    [UnmanagedFunctionPointerAttribute(CallingConvention.StdCall)]    
    public delegate void ACTION_CALLBACK(lb_event_message_e userEvent, IntPtr wParam, IntPtr userData); 

    public class LonBonFun         
    {                    
        [DllImport("lb_sdk_universal.dll")] 
        public static extern int lb_initialServer(string serverIp, int svrPort);  //初始化   

        [DllImport("lb_sdk_universal.dll")] 
        public static extern int lb_CallActionNotify(ACTION_CALLBACK callback, IntPtr userData);  //注册回调函数    

        [DllImport("lb_sdk_universal.dll")]
        public static extern int lb_releaseServer();  //释放SDK

    }
  [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]  
        public struct ActionParam
        {
            public int sender; // 发送端
            public int receiver; // 接收端
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)]
            public string acceptBc; // 广播接收端
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)]
            public string SessionId; // 会话标识
            public int broadId; // 广播组序(标识)/门磁编号
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 512)]
            public string rdFile; // 录音文件名  
            public int atmTerNum; // Atm编号   
        }  
 class Program
    {  
        public static ACTION_CALLBACK callback ;    
        static void Main(string[] args)  
        {   
            int result = LonBonFun.lb_initialServer("192.168.1.94", 5160); 
            Console.WriteLine("已完成初始化");
            callback = callFun;
            LonBonFun.lb_CallActionNotify(callback, (IntPtr)0); 
            Console.ReadKey();  
        }  
        static private void callFun(lb_event_message_e userEvent, IntPtr wParam, IntPtr userData) 
        {
            if (userEvent == 9 || userEvent == 10)  
            {
                ActionParam tActionParam = new ActionParam();
                tActionParam = (ActionParam)Marshal.PtrToStructure(wParam,typeof(ActionParam));
                Console.WriteLine(tActionParam.rdFile);   
            }    
        }    
    }

注:到这里正文开始了,

  方法一:结构体添加属性CharSet = CharSet.Ansi。   

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] 

  原因: 首先结构体CharSet属性 是决定字符串封送的方式,共有三种。Unicode将字符串封送为Unicode格式,Ansi为字符串封送为Ansi格式,Auto将字符串随机应变封送

  方法二:一般C++结构体用的字符数组char[],但我们在C#一律都换成字节数组byte[], 封送类型从 ByValTStr 改成 ByValArray

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 512)]
public byte[] rdFile; // 录音文件名

 然后用

System.Text.Encoding.UTF8.GetString(tActionParam .rdFile);

  获取,即完成(一般是UTF8)。

原文地址:https://www.cnblogs.com/HansZimmer/p/10757043.html