• (二)一个工作任务引起的乱战——C++程序编译为dll,让C#调用


    C++程序编译为C#可调用的dll的过程:

    1.新建一个Win32 Console Application 项目,项目名为:DLLDemo,下一步选择Application type为DLL;

    2.在Source Files文件夹的DLLDemo.cpp文件中加入代码:

    extern "C" _declspec(dllexport) int Add(int a,int b){
        return a+b;
    }

    这个函数将在C#中调用。

    3.build项目。

    会在D:\visualStudio\Projects\DLLDemo\Debug看到DLLDemo.dll文件,该文件就是要被C#调用的dll。

    C#调用C++dll的方法:

    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.Runtime.InteropServices;
    
    namespace InteropDemo
    {
        class Program
        {
            [DllImport("D:\visualStudio\Projects\DLLDemo\Debug\DLLDemo.dll", EntryPoint = "Add", CallingConvention = CallingConvention.Cdecl)]
            public static extern int Add(int a, int b); //DllImport请参照MSDN
    
            static void Main(string[] args)
            {
                Console.WriteLine(Add(1, 2));
                Console.Read();
            }
        }
    }

     【运行结果】:

    3

    注意:CallingConvention = CallingConvention.Cdecl参数很重要,如果没有错,会抛异常。

    这是Windows下c++程序编译成dll供c#调用的方法,可惜还是不能解决工作任务,因为那个api是Linux下的源码。于是,我只能自己写代码,包装请求参数,发消息。下面的文字是我处理工作任务的过程,可以跳过不看,因为没有处理成功,对你们可能没有太大的帮助。

    现在介绍下服务接入文档,其请求包要求如下:

    上图请求包中参数m_sContent的格式如下:

    如果自己包装请求,这里存在两个问题不知道怎么解决:

    首先,两图中结构体每个成员的需要限定长度;

    其次,在请求包中m_sContent本来是规定为string类型的,又做了另一个规定为结构体,这中间存在一个转换问题,理解不透。

    在处理这个问题的过程中,我采用了三种方法:

    首先定义的结构体为:

    //请求包结构体定义
            public struct ReqPackage
            {
                public string m_cVersion;//协议的版本号
                public uint m_dwNeedRst;//是否需要返回
                public uint m_dwCmd;//请求的服务类型
                public uint m_dwContentLen;//内容有效长度
                public string m_sContent;//内容为请求命令或者返回的相关信息
                public uint m_dwPkgSeq;//upd包序列号,tcp下为0
            };
    
            //消息内容结构体定义
            public struct MsgReq
            {
                public uint m_iFuid;// 用户ID
                public int m_iMask;//发送屏蔽码*
                public int m_iMsgLen;//消息的有效长度
                public string m_sMsgContent;//消息
            }

    1.将两个结构体转化为byte[]然后处理长度。处理过程有误,没有成功;后来发现这段代码也有错误,不能这样处理。

      //将请求包各参数按长度组合好
            public byte[] ReqPackageTo(ReqPackage reqPackage)
            {
                byte[] structudp = StructToBytes(reqPackage);
                List<byte> bufferIn = new List<byte>();
                var parametersVer = new byte[4];
                parametersVer = BitConverter.GetBytes(structudp[0]);
                bufferIn.AddRange(parametersVer);
                for (int i = 1; i < structudp.Length; i++)
                {
                    if (i != 4)
                    {
                        var parameters = new byte[4];
                        parameters = BitConverter.GetBytes(structudp[i]);
                        bufferIn.AddRange(parameters);
                    }
                    else//消息内容实际长度以m_dwContentLen为准,最大长度为846字节
                    {
                        uint sizeCon = reqPackage.m_dwContentLen;
                        var parametersCon = new byte[sizeCon];
                        parametersCon = System.Text.Encoding.Default.GetBytes(reqPackage.m_sContent);
                        bufferIn.AddRange(parametersCon);
                    }
    
                }
                return bufferIn.ToArray();
            }
    
    
            //将消息内容各参数按长度组合好
            public byte[] MsgReqTo(MsgReq msgReq)
            {
                byte[] structMsg = StructToBytes(msgReq);
                List<byte> bufferIn = new List<byte>();
                for (int i = 1; i < structMsg.Length; i++)
                {
                    if (i != 3)
                    {
                        var parameters = new byte[4];
                        parameters = BitConverter.GetBytes(structMsg[i]);
                        bufferIn.AddRange(parameters);
                    }
                    else//消息内容实际长度以m_iMsgLen为准,最大长度为846字节
                    {
                        int sizeCon = msgReq.m_iMsgLen;
    
                        var parametersCon = new byte[sizeCon];
                        parametersCon = parametersCon = System.Text.Encoding.Default.GetBytes(msgReq.m_sMsgContent);
                        bufferIn.AddRange(parametersCon);
                    }
    
                }
                return bufferIn.ToArray();
            } 

    2.将m_sContent结构体的各个成员单独处理,均先转换为byte[],限定长度,然后转换成一个byte[],再转换成string(为的是赋值给请求包中m_sContent)。然后将请求包中的各个成员单独处理,均先转换为byte[],限定长度,然后转换成一个byte[]。没有成功;

    //将请求包各参数按长度组合好
            public byte[] reqPackBytes(ReqPackage reqp)
            {
                List<byte> bufferIn = new List<byte>();
                var m_cVersion = new byte[1];
                m_cVersion = System.Text.Encoding.Default.GetBytes(reqp.m_cVersion);
                var m_dwCmd = new byte[4];
                m_dwCmd = System.BitConverter.GetBytes(reqp.m_dwCmd);
                var m_dwNeedRst = new byte[4];
                m_dwNeedRst = System.BitConverter.GetBytes(reqp.m_dwNeedRst);
                //var m_dwPkgSeq = new byte[4];
                //m_dwPkgSeq=System.BitConverter.GetBytes(reqp.m_dwPkgSeq);
                var m_dwContentLen = new byte[4];
                m_dwContentLen = System.BitConverter.GetBytes(reqp.m_dwContentLen);
                byte[] m_sContent = System.Text.Encoding.Default.GetBytes(reqp.m_sContent);
                bufferIn.AddRange(m_cVersion);
                bufferIn.AddRange(m_dwCmd);
                bufferIn.AddRange(m_dwNeedRst);
                bufferIn.AddRange(m_dwContentLen);
                bufferIn.AddRange(m_sContent);
                //   bufferIn.AddRange(m_dwPkgSeq);
                return bufferIn.ToArray();
            }
    
    
            //将消息内容各参数按长度组合好
            public byte[] msConBytes(MsgReq msgR)
            {
                List<byte> bufferIn = new List<byte>();
                var m_iFuid = new byte[4];
                m_iFuid = System.BitConverter.GetBytes(msgR.m_iFuid);
                var m_iMask = new byte[4];
                m_iMask = System.BitConverter.GetBytes(msgR.m_iMask);
                var m_iMsgLen = new byte[4];
                m_iMsgLen = System.BitConverter.GetBytes(msgR.m_iMsgLen);
                byte[] m_sMsgContent = System.Text.Encoding.Default.GetBytes(msgR.m_sMsgContent);
                bufferIn.AddRange(m_iFuid);
                bufferIn.AddRange(m_iMask);
                bufferIn.AddRange(m_iMsgLen);
                bufferIn.AddRange(m_sMsgContent);
                return bufferIn.ToArray();
            }

    3.比较笨的一种方法,手动拼字节。没有成功。

    StringBuilder msgBodyBuffer = new StringBuilder(846);//m_sContent
                    String msgBody = msgBodyBuffer.ToString();
                    byte[] msgBodyBytes = System.Text.Encoding.Default.GetBytes(msgBody);
                    byte[] msg = new byte[859];     
                    msg[0] = 0x02; // 协议版本
                    msg[1] = 0;
                    msg[2] = 0;
                    msg[3] = 0;
                    msg[4] = (byte)1; // 是否响应
                    msg[5] = 0;
                    msg[6] = 0;
                    msg[7] = 0;
                    msg[8] = 0;
                    msg[9] = 0;
                    msg[10] = 0;
                    msg[11] = 0; // 请求的服务类型
                    msg[12] = (byte)(0x325 & 0xFF); // 请求命令的有效长度, 为什么是0x2D?
                    msg[13] = (byte)((0x325 >> 8) & 0xFF);
                    msg[14] = 0;
                    msg[15] = 0;
                    uint uid = 0;
                    String uidStr = Fuid;
                    if (uidStr != null && uidStr.Length > 0)
                        uid = uint.Parse(uidStr);
                    msg[17] = (byte)(uid & 0xFF);
                    msg[18] = (byte)((uid >> 8) & 0xFF);
                    msg[19] = (byte)((uid >> 16) & 0xFF);
                    msg[20] = (byte)((uid >> 24) & 0xFF);
                    msg[21] = 0;
                    msg[22] = 0;
                    msg[23] = 0;
                    msg[24] = (byte)1; // 发送屏蔽码
                    int length = msgBodyBytes.Length;
                    if (length > 834)
                        length = 834;
                    msg[25] = 0;
                    msg[26] = 0;
                    msg[27] = (byte)(length & 0xFF);  // 消息的有效长度
                    msg[28] = (byte)((length >> 8) & 0xFF);
                    Array.Copy(msgBodyBytes, 0, msg, 28, length);

    整了不少时间还没整出来,备受打击。希望能找到解决方法。

    下一文将介绍udp通信。

  • 相关阅读:
    PyCharm使用(完全图解(最新经典))
    pg存储过程学习
    sql_to_sqlalchemy
    python中嵌入lua解析器
    Python和lua互相调用
    Lupa
    [cb] Unity Editor 添加右键菜单
    [C#] 委托之Action和Func区别
    [反编译U3D]Decompile Unity Resources
    [cb] Assetbundle打包(一)
  • 原文地址:https://www.cnblogs.com/echolxl/p/3146375.html
Copyright © 2020-2023  润新知