您的位置:首页 > 其它

某联接口由控件对象模式转为结构过程模式的操作

2016-09-23 14:49 666 查看
//输入输出的结构体变量
struct REQUEST
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] posid;//POS机号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] operid;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] trans;//交易类型
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public char[] amount;//金额
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] old_date;//原交易日期
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public char[] old_reference;//原交易参/考号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public char[] old_trace;//原凭证号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public char[] lrc;//LRC校验

};
struct RESPONSE
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public char[] resp_code;//返回码
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] bank_code; //银行行号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 20)]
public char[] card_no;  //卡号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public char[] trace;     //凭证号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public char[] amount;   //金额
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 40)]
public char[] resp_chin;//错误说明
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 15)]
public char[] mei_id;   //商户号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] ter_id;    //终端号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public char[] batch_no;  //批次号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] txndate;   //交易日期
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public char[] txntime;   //交易时间
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 12)]
public char[] refdata;  //系统参考号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
public char[] authcode;  //授权号
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)]
public char[] stdate;    //清算日期
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
public char[] lrc;       //LRC校验
}

[DllImport("posinf.dll", CharSet = CharSet.Ansi, SetLastError = true)]
public static extern int bankall(char[] str1, byte[] str2);


最终调用:
StringBuilder str1;
REQUEST strin;
string str;
str1 = new StringBuilder();
byte[] str2 = new byte[1024];
strin.posid = new char[8];
strin.posid = textBox1.Text.ToCharArray();
strin.operid = new char[8];
strin.operid = textBox2.Text.ToCharArray();
strin.trans = new char[2];
strin.trans = comboBox1.Text.Substring(0, 2).ToCharArray();
strin.amount = new char[12];
strin.amount = textBox4.Text.ToCharArray();
strin.old_date = new char[8];
strin.old_date = textBox5.Text.ToCharArray();
strin.old_reference = new char[12];
strin.old_reference = textBox6.Text.ToCharArray();
strin.old_trace = new char[6];
strin.old_trace = textBox7.Text.ToCharArray();
strin.lrc = new char[3];
strin.lrc = textBox8.Text.ToCharArray();
str1.Append(strin.posid);
str1.Append(strin.operid);
str1.Append(strin.trans);
str1.Append(strin.amount);
str1.Append(strin.old_date);
str1.Append(strin.old_reference);
str1.Append(strin.old_trace);
str1.Append(strin.lrc);
bankall(str1.ToString().ToCharArray(), str2);
string tranresult;
tranresult = System.Text.Encoding.GetEncoding("gb2312").GetString(str2);
textBox9.Text = tranresult.Substring(0, 144);
str = textBox9.Text.Substring(0, 2);
if (str == "00")
{
textBox10.Text = textBox9.Text.Substring(0, 2);
textBox11.Text = textBox9.Text.Substring(2, 4);
textBox12.Text = textBox9.Text.Substring(6, 20);
textBox13.Text = textBox9.Text.Substring(26, 6);
textBox14.Text = textBox9.Text.Substring(32, 12);
textBox24.Text = textBox9.Text.Substring(44, 36);
textBox15.Text = textBox9.Text.Substring(80, 15);
textBox16.Text = textBox9.Text.Substring(95, 8);
textBox17.Text = textBox9.Text.Substring(103, 6);
textBox18.Text = textBox9.Text.Substring(109, 4);
textBox19.Text = textBox9.Text.Substring(113, 6);
textBox20.Text = textBox9.Text.Substring(119, 12);
textBox21.Text = textBox9.Text.Substring(131, 6);
textBox22.Text = textBox9.Text.Substring(137, 4);
textBox23.Text = textBox9.Text.Substring(141, 3);
}
else
{
textBox10.Text = textBox9.Text.Substring(0, 2);
textBox24.Text = textBox9.Text.Substring(44, 36);
}


相关知识:

作用:

MarshalAs属性指示如何在托管代码和非托管代码之间封送数据。

使用方法:

[MarshalAs(UnmanagedType unmanagedType, 命名参数)]

实际上相当于构造一个MarshalAsAttribute类的对象

常用的UnmanagedType枚举值:(详细内容查MSDN)

BStr 长度前缀为双字节的 Unicode 字符串;

LPStr 单字节、空终止的 ANSI 字符串。;

LPWStr 一个 2 字节、空终止的 Unicode 字符串;

ByValArray 用于在结构中出现的内联定长字符数组,应始终使用MarshalAsAttribute的SizeConst字段来指示数组的大小。

注意:

在用Marshal.SizeOf(),即获取对象的非托管大小时,获得的是自己定义的大小;

但在实际处理的时候,是按照实际的大小来获取的

示例:

定义一个固定大小的结构体,代码如下:

结构的声明:

[csharp] view
plain copy

struct Info

{

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]

public char[] name;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]

public char[] cipher;

[MarshalAs(UnmanagedType.ByValArray, SizeConst = 256)]

public char[] signature;

}

结构的使用:

[csharp] view
plain copy

Info myInfo;

myInfo.name = name.ToCharArray();

myInfo.cipher = cipher.ToCharArray();

myInfo.signature = signature.ToCharArray();

注意:

[csharp] view
plain copy

int size = Marshal.SizeOf(myInfo);

size=16+16+256

可见,获取到的非托管大小为288

但是,查看myInfo对象可以看到其实际大小如下所示:



问题:

这种实际大小和固定大小的不一致性,导致了在用Marshal类进行托管对象和非托管对象的转换时,会有如下错误提示:“未能封送类型,因为嵌入数组实例的长度与布局中声明的长度不匹配。”

解决办法还没想到......

小结:

MarshalAs这个属性很难用,很容易用错,用好需要对C#、C++和COM数据的布局方式有一定的了解才能做。所以做好使用一些工具来帮你,可以参照我下面的文章:

http://blog.csdn.net/Donjuan/archive/2009/02/05/3865026.aspx

如果你只是感兴趣的话,那就忘了这个属性吧,在.NET 4.0以后,微软会尽量解决掉这个属性。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐