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

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

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

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

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

3.build项目。

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

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

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Text;
  4. using System.Runtime.InteropServices;
  5.  
  6. namespace InteropDemo
  7. {
  8. class Program
  9. {
  10. [DllImport("D:\\visualStudio\\Projects\\DLLDemo\\Debug\\DLLDemo.dll", EntryPoint = "Add", CallingConvention = CallingConvention.Cdecl)]
  11. public static extern int Add(int a, int b); //DllImport请参照MSDN
  12.  
  13. static void Main(string[] args)
  14. {
  15. Console.WriteLine(Add(, ));
  16. Console.Read();
  17. }
  18. }
  19. }

【运行结果】:

3

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

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

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

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

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

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

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

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

首先定义的结构体为:

  1. //请求包结构体定义
  2. public struct ReqPackage
  3. {
  4. public string m_cVersion;//协议的版本号
  5. public uint m_dwNeedRst;//是否需要返回
  6. public uint m_dwCmd;//请求的服务类型
  7. public uint m_dwContentLen;//内容有效长度
  8. public string m_sContent;//内容为请求命令或者返回的相关信息
  9. public uint m_dwPkgSeq;//upd包序列号,tcp下为0
  10. };
  11.  
  12. //消息内容结构体定义
  13. public struct MsgReq
  14. {
  15. public uint m_iFuid;// 用户ID
  16. public int m_iMask;//发送屏蔽码*
  17. public int m_iMsgLen;//消息的有效长度
  18. public string m_sMsgContent;//消息
  19. }

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

  1. //将请求包各参数按长度组合好
  2. public byte[] ReqPackageTo(ReqPackage reqPackage)
  3. {
  4. byte[] structudp = StructToBytes(reqPackage);
  5. List<byte> bufferIn = new List<byte>();
  6. var parametersVer = new byte[];
  7. parametersVer = BitConverter.GetBytes(structudp[]);
  8. bufferIn.AddRange(parametersVer);
  9. for (int i = ; i < structudp.Length; i++)
  10. {
  11. if (i != )
  12. {
  13. var parameters = new byte[];
  14. parameters = BitConverter.GetBytes(structudp[i]);
  15. bufferIn.AddRange(parameters);
  16. }
  17. else//消息内容实际长度以m_dwContentLen为准,最大长度为846字节
  18. {
  19. uint sizeCon = reqPackage.m_dwContentLen;
  20. var parametersCon = new byte[sizeCon];
  21. parametersCon = System.Text.Encoding.Default.GetBytes(reqPackage.m_sContent);
  22. bufferIn.AddRange(parametersCon);
  23. }
  24.  
  25. }
  26. return bufferIn.ToArray();
  27. }
  28.  
  29. //将消息内容各参数按长度组合好
  30. public byte[] MsgReqTo(MsgReq msgReq)
  31. {
  32. byte[] structMsg = StructToBytes(msgReq);
  33. List<byte> bufferIn = new List<byte>();
  34. for (int i = ; i < structMsg.Length; i++)
  35. {
  36. if (i != )
  37. {
  38. var parameters = new byte[];
  39. parameters = BitConverter.GetBytes(structMsg[i]);
  40. bufferIn.AddRange(parameters);
  41. }
  42. else//消息内容实际长度以m_iMsgLen为准,最大长度为846字节
  43. {
  44. int sizeCon = msgReq.m_iMsgLen;
  45.  
  46. var parametersCon = new byte[sizeCon];
  47. parametersCon = parametersCon = System.Text.Encoding.Default.GetBytes(msgReq.m_sMsgContent);
  48. bufferIn.AddRange(parametersCon);
  49. }
  50.  
  51. }
  52. return bufferIn.ToArray();
  53. }

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

  1. //将请求包各参数按长度组合好
  2. public byte[] reqPackBytes(ReqPackage reqp)
  3. {
  4. List<byte> bufferIn = new List<byte>();
  5. var m_cVersion = new byte[];
  6. m_cVersion = System.Text.Encoding.Default.GetBytes(reqp.m_cVersion);
  7. var m_dwCmd = new byte[];
  8. m_dwCmd = System.BitConverter.GetBytes(reqp.m_dwCmd);
  9. var m_dwNeedRst = new byte[];
  10. m_dwNeedRst = System.BitConverter.GetBytes(reqp.m_dwNeedRst);
  11. //var m_dwPkgSeq = new byte[4];
  12. //m_dwPkgSeq=System.BitConverter.GetBytes(reqp.m_dwPkgSeq);
  13. var m_dwContentLen = new byte[];
  14. m_dwContentLen = System.BitConverter.GetBytes(reqp.m_dwContentLen);
  15. byte[] m_sContent = System.Text.Encoding.Default.GetBytes(reqp.m_sContent);
  16. bufferIn.AddRange(m_cVersion);
  17. bufferIn.AddRange(m_dwCmd);
  18. bufferIn.AddRange(m_dwNeedRst);
  19. bufferIn.AddRange(m_dwContentLen);
  20. bufferIn.AddRange(m_sContent);
  21. // bufferIn.AddRange(m_dwPkgSeq);
  22. return bufferIn.ToArray();
  23. }
  24.  
  25. //将消息内容各参数按长度组合好
  26. public byte[] msConBytes(MsgReq msgR)
  27. {
  28. List<byte> bufferIn = new List<byte>();
  29. var m_iFuid = new byte[];
  30. m_iFuid = System.BitConverter.GetBytes(msgR.m_iFuid);
  31. var m_iMask = new byte[];
  32. m_iMask = System.BitConverter.GetBytes(msgR.m_iMask);
  33. var m_iMsgLen = new byte[];
  34. m_iMsgLen = System.BitConverter.GetBytes(msgR.m_iMsgLen);
  35. byte[] m_sMsgContent = System.Text.Encoding.Default.GetBytes(msgR.m_sMsgContent);
  36. bufferIn.AddRange(m_iFuid);
  37. bufferIn.AddRange(m_iMask);
  38. bufferIn.AddRange(m_iMsgLen);
  39. bufferIn.AddRange(m_sMsgContent);
  40. return bufferIn.ToArray();
  41. }

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

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

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

下一文将介绍udp通信。

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

  1. (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换

    一个工作任务涉及到c#与c++系统间的udp通信,处理了蛮长时间没有完成任务,但是期间接触到不少小知识点.本人是初接触c#,c++语言没有接触过.可能写的东西都很小儿科,暂且记录下来当工作日记把. 先 ...

  2. (三)一个工作任务引起的乱战——udp通信

    先上代码.该代码是在问度娘的过程中搜到的,自己实验运行了下,可以使用(vs2010  net fram4.0).服务端代码: using System;using System.Collections ...

  3. 一个工作了四年的java程序员的心得体会

    年底了,该给自己写点总结了!从毕业到现在已经快4年啦,一直在Java的WEB开发行业混迹.我不是牛人,但是自我感觉还算是个合格的程序员,有必要写下自己将近4年来的经历,给自我以提示,给刚入行的朋友提供 ...

  4. 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序

    如何在Visual Studio 2017中使用C# 7+语法   前言 之前不知看过哪位前辈的博文有点印象C# 7控制台开始支持执行异步方法,然后闲来无事,搞着,搞着没搞出来,然后就写了这篇博文,不 ...

  5. Struts2(二):工作原理

    struts可查看源码:https://github.com/apache/struts 在学习struts2之前,我先看了一些比较早版本对struts2的工作原理相关的介绍,顺便抄写过来,用来帮助自 ...

  6. 在Excel里如何将多个工作簿合并到一个工作簿中

    在Excel里如何将多个工作簿合并到一个工作簿中 当你必须将多个工作簿合并到一个工作簿时,你遇到过麻烦吗?最让人心烦的就是需要合并的工作簿里有很多张工作表.有人能推荐方法解决这个问题吗? 利用VBA ...

  7. EXCEL 如何将多个工作表或工作簿合并到一个工作表

    在使用Excel 时,我们经常需要将多个工作表或工作簿合并到一个工作表中,这样我们就能快速地对数据进行分析和统计.对于一般用户而言,除了复制每个工作表后再粘贴,没有其他什么方法了.如果只是合并少数几个 ...

  8. 用VBA宏从一个工作薄复制内容到另一个工作薄

    我们项目管理有两个工作薄,一个里面有多个表,每天建一个,记录当天项目,另一个工作薄,有多个表,其中一个是所有项目汇总. 以前都是第一个工作薄一个表做完,再复制粘贴到第二个工作薄的汇总表中. 写了个VB ...

  9. Excel 2010 如何将筛选后的数据复制粘贴到另一个工作表筛选后的表格里

    如果你是指自动筛选后,把筛选数据复制/粘贴到另外一个工作表中,不妨试试试 第一步选中筛选后的数据区域:第二步执行菜单命令“编辑/定位/定位条件/可见单元格”,确定:第三步单击复制按钮或者Ctrl+C或 ...

随机推荐

  1. python的exec、eval详解

    exec exec语句用来执行储存在字符串或文件中的Python语句.例如,我们可以在运行时生成一个包含Python代码的字符串,然后使用exec语句执行这些语句.下面是一个简单的例子. exec ' ...

  2. 武汉科技大学ACM :1001: 零起点学算法34——继续求多项式

    Problem Description 输入1个正整数n, 计算1+(1+2)+(1+2+3)+...+(1+2+3+...+n) Input 输入正整数n(多组数据) Output 输出1+(1+2 ...

  3. 你好,C++(13)这道单选题的答案是A、B、C还是D?3.7 枚举类型

    3.7  枚举类型 除了之前我们介绍的数值数据和文字数据之外,在现实世界中,常常还会遇到这样一类数据:一道单选题的答案只能是A.B.C.D四个选项中的某一个:红绿灯的颜色只能是红色,绿色和黄色中的某一 ...

  4. jQuery上传插件Uploadify 3.2使用

    Uploadify下载地址:http://www.uploadify.com/download/ 这里下载最新版的3.2的. 常用API描述: $(document).ready(function() ...

  5. php explode 用法详解

    定义和用法explode() 函数把字符串分割为数组. 语法explode(separator,string,limit)参数 描述 separator 必需.规定在哪里分割字符串.string 必需 ...

  6. Java内部类和外部类的通信探索

    1.内部类访问外部类的成员和方法 在内部类中,可以无障碍地访问外部类的所有成员和方法. 在下面的实验代码中,可以看到,内部类sl可以访问外部类的私有成员:sz 和 cur. 同时可以访问私有方法:pr ...

  7. Xcode 如何设置 自动内存管理 转换为 手动内存管理

    建议使用自动内存管理 ARC. 如果不想自动内存管理,可以在build phases 下的compile sources 中找到不想自动管理的.m文件 ,给它加compiler flags 为 -fn ...

  8. Entity Framewor 学习笔记 (碎碎的东西)

    Proxy 类代理类是为了让EF实现lazy load才需要的 public class BloggingContext : DbContext {     public BloggingContex ...

  9. uva 10026 Shoemaker's Problem

    http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&p ...

  10. HDOJ(HDU) 1562 Guess the number(水题,枚举就行)

    Problem Description Happy new year to everybody! Now, I want you to guess a minimum number x betwwn ...