(二)一个工作任务引起的乱战——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(, ));
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[];
parametersVer = BitConverter.GetBytes(structudp[]);
bufferIn.AddRange(parametersVer);
for (int i = ; i < structudp.Length; i++)
{
if (i != )
{
var parameters = new byte[];
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 = ; i < structMsg.Length; i++)
{
if (i != )
{
var parameters = new byte[];
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[];
m_cVersion = System.Text.Encoding.Default.GetBytes(reqp.m_cVersion);
var m_dwCmd = new byte[];
m_dwCmd = System.BitConverter.GetBytes(reqp.m_dwCmd);
var m_dwNeedRst = new byte[];
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[];
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[];
m_iFuid = System.BitConverter.GetBytes(msgR.m_iFuid);
var m_iMask = new byte[];
m_iMask = System.BitConverter.GetBytes(msgR.m_iMask);
var m_iMsgLen = new byte[];
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();//m_sContent
String msgBody = msgBodyBuffer.ToString();
byte[] msgBodyBytes = System.Text.Encoding.Default.GetBytes(msgBody);
byte[] msg = new byte[];
msg[] = 0x02; // 协议版本
msg[] = ;
msg[] = ;
msg[] = ;
msg[] = (byte); // 是否响应
msg[] = ;
msg[] = ;
msg[] = ;
msg[] = ;
msg[] = ;
msg[] = ;
msg[] = ; // 请求的服务类型
msg[] = (byte)(0x325 & 0xFF); // 请求命令的有效长度, 为什么是0x2D?
msg[] = (byte)((0x325 >> ) & 0xFF);
msg[] = ;
msg[] = ;
uint uid = ;
String uidStr = Fuid;
if (uidStr != null && uidStr.Length > )
uid = uint.Parse(uidStr);
msg[] = (byte)(uid & 0xFF);
msg[] = (byte)((uid >> ) & 0xFF);
msg[] = (byte)((uid >> ) & 0xFF);
msg[] = (byte)((uid >> ) & 0xFF);
msg[] = ;
msg[] = ;
msg[] = ;
msg[] = (byte); // 发送屏蔽码
int length = msgBodyBytes.Length;
if (length > )
length = ;
msg[] = ;
msg[] = ;
msg[] = (byte)(length & 0xFF); // 消息的有效长度
msg[] = (byte)((length >> ) & 0xFF);
Array.Copy(msgBodyBytes, , msg, , length);
整了不少时间还没整出来,备受打击。希望能找到解决方法。
下一文将介绍udp通信。
(二)一个工作任务引起的乱战——C++程序编译为dll,让C#调用的更多相关文章
- (一)一个工作任务引起的乱战——c#中结构体与byte[]间相互转换
一个工作任务涉及到c#与c++系统间的udp通信,处理了蛮长时间没有完成任务,但是期间接触到不少小知识点.本人是初接触c#,c++语言没有接触过.可能写的东西都很小儿科,暂且记录下来当工作日记把. 先 ...
- (三)一个工作任务引起的乱战——udp通信
先上代码.该代码是在问度娘的过程中搜到的,自己实验运行了下,可以使用(vs2010 net fram4.0).服务端代码: using System;using System.Collections ...
- 一个工作了四年的java程序员的心得体会
年底了,该给自己写点总结了!从毕业到现在已经快4年啦,一直在Java的WEB开发行业混迹.我不是牛人,但是自我感觉还算是个合格的程序员,有必要写下自己将近4年来的经历,给自我以提示,给刚入行的朋友提供 ...
- 如何在Visual Studio 2017中使用C# 7+语法 构建NetCore应用框架之实战篇(二):BitAdminCore框架定位及架构 构建NetCore应用框架之实战篇系列 构建NetCore应用框架之实战篇(一):什么是框架,如何设计一个框架 NetCore入门篇:(十二)在IIS中部署Net Core程序
如何在Visual Studio 2017中使用C# 7+语法 前言 之前不知看过哪位前辈的博文有点印象C# 7控制台开始支持执行异步方法,然后闲来无事,搞着,搞着没搞出来,然后就写了这篇博文,不 ...
- Struts2(二):工作原理
struts可查看源码:https://github.com/apache/struts 在学习struts2之前,我先看了一些比较早版本对struts2的工作原理相关的介绍,顺便抄写过来,用来帮助自 ...
- 在Excel里如何将多个工作簿合并到一个工作簿中
在Excel里如何将多个工作簿合并到一个工作簿中 当你必须将多个工作簿合并到一个工作簿时,你遇到过麻烦吗?最让人心烦的就是需要合并的工作簿里有很多张工作表.有人能推荐方法解决这个问题吗? 利用VBA ...
- EXCEL 如何将多个工作表或工作簿合并到一个工作表
在使用Excel 时,我们经常需要将多个工作表或工作簿合并到一个工作表中,这样我们就能快速地对数据进行分析和统计.对于一般用户而言,除了复制每个工作表后再粘贴,没有其他什么方法了.如果只是合并少数几个 ...
- 用VBA宏从一个工作薄复制内容到另一个工作薄
我们项目管理有两个工作薄,一个里面有多个表,每天建一个,记录当天项目,另一个工作薄,有多个表,其中一个是所有项目汇总. 以前都是第一个工作薄一个表做完,再复制粘贴到第二个工作薄的汇总表中. 写了个VB ...
- Excel 2010 如何将筛选后的数据复制粘贴到另一个工作表筛选后的表格里
如果你是指自动筛选后,把筛选数据复制/粘贴到另外一个工作表中,不妨试试试 第一步选中筛选后的数据区域:第二步执行菜单命令“编辑/定位/定位条件/可见单元格”,确定:第三步单击复制按钮或者Ctrl+C或 ...
随机推荐
- Java反射 - 1(得到类对象的几种方法,调用方法,得到包下的所有类)
通过反射获得对象的方法 准备工作: 有一个User类如下 package o1; /** * Created by yesiming on 16-11-19. */ public class User ...
- thrift之TTransport类体系原理及源码详细解析1-类结构和抽象基类
本章主要介绍Thrift的传输层功能的实现,传输的方式多种多样,可以采用压缩.分帧等,而这些功能的实现都是相互独立,和上一章介绍的协议类实现方式比较雷同,还是先看看这部分的类关系图,如下: 由上面的类 ...
- 10.使用final关键字修饰一个变量时...
10.使用final关键字修饰一个变量时,是引用不能变,还是引用的对象不能变? 答:引用不能变,不能将引用再次指向另一个新的对象,但引用所指向的对象中的内容是可以改变的. 补充: 1.对于基本类型,f ...
- Css预处理器实践之Sass、Less大比拼
xwei | 2012-07-07 | 网页重构 什么是CSS预处理器? Css可以让你做很多事情,但它毕竟是给浏览器认的东西,对开发者来说,Css缺乏很多特性,例如变量.常量以及一些编程语法,代码难 ...
- centOS上安装redis
1.安装tcl支持 yum install tcl 2.安装redis我们以最新的2.8.9为例 $ wget http://download.redis.io/releases/redis-2.8. ...
- IE6浏览器兼容问题及部分解决方案(网上整理)
作为一个初涉前端技术的IT菜鸟,IE浏览器的兼容问题是一个不得不跨越的坎.为了能够在不同浏览器达到同样的显示效果,就不得不花心思想出办法实现兼容.由于各大主流浏览器内核不同,各自的实现标准有所差异,因 ...
- java构造方法的不同
分为有参数和无参数,还有THIS的使用方法,可用于传递给类,也可用于调用其它构造方法. public class Book { private String name; public Book(){ ...
- bootstrap栅格布局,第一次成功
代码: <div class="helper" style="background-color: #F7F7F9;height: 200px;padding-top ...
- android实现类似于支付宝余额快速闪动的效果
效果如下: 此图片不会动,但实际上是会快速跳动的. 之前看到有支付宝的效果非常牛逼.就是进去看到余额呼噜噜的直接上蹿下跳到具体数字,效果帅,但不知道怎么实现,最近终于知道了. 思路: 首先经常用 ...
- gcc编译时头文件库文件搜索顺序(转)
原文: http://blog.csdn.net/silentfly1987/article/details/6119195