日期:2014-05-18  浏览次数:20981 次

关于C#调用VC++6.0 DLL的问题
原始dll声明如下:
dll调用(posinf.dl)函数名为:int bankall (char * request,char *response),其中第一个参数为传入参数。
ocx调用(umsocx.ocx):trans(),传入参数为:bankrequest
请求参数格式说明如下:
内容 格式 长度 描述
POS机号 ANS 8 不足右补空格
POS员工号 ANS 8 不足右补空格
交易类型标志 N 2 '00'-消费 '01'-撤消
'02'-退货 '03'-查余额
'04'-重打印 '05'-签到
'06'-结算 '07'-重打结算单
'08'-全民付 '55'-换班统计
'10'-积分消费 '11'-积分撤消
'12'-分期消费 '13'-分期撤销
'21'-'26':预授权类交易
金额 N 12 信用卡消费金额,char(12),没有小数点".",精确到分,最后两位为小数位,不足左补0。
原交易日期 N 8 yyyymmdd格式,退货时用,其他交易空格
原交易参考号 N 12 退货时用,其他交易空格
原凭证号 N 6 撤消时用,其他交易空格
LRC校验 ANS 3 3位随机数字

dll调用(posinf.dl)函数名为:int bankall (char * request,char *response),其中第二个参数为应答参数。
ocx调用函数名为:trans(),传入参数为:BankResponse
应答参数格式说明如下:
内容 格式 长度 描 述
返回码 N 2 00 表示成功,其它表示失败
银行行号 N 4 发卡行代码
卡号 N 20 卡号(屏蔽部分,保留前6后4)
凭证号 N 6
金额 N 12
错误说明 ANS 40 中文解释
商户号 N 15
终端号 N 8
批次号 N 6
交易日期 N 4
交易时间 N 6
交易参考号 N 12
授权号 N 6
清算日期 N 4
LRC校验 ANS 3 三位数字,应该和请求一致

--------------------------------------
使用以下C#代码调用时总出现System.AccessViolationException: 尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
C#代码如下:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace WindowsApplication1
{
  public partial class Form1 : Form
  {
  [DllImport(@"posinf.dll", CallingConvention = CallingConvention.Cdecl, SetLastError = true, CharSet = CharSet.Ansi, EntryPoint = @"bankall")]
  static extern int bankall(string request, out string response);//尝试过使用byte[],char[],StringBuilder以及ref修饰符均未解决问题。CallingConvention.stdcall也尝试过。

  public Form1()
  {
  InitializeComponent();
  }

  private void button1_Click(object sender, EventArgs e)
  {
   
  string str = null;
  int p = -9;
  string ss = "";

  ss = ss.PadLeft(148, ' ');  
  str = "POS12345";
  str += "USER1234";
  str += "02";
  str += "000000005000";
  str += "20120302";
  str += "172900123456";
  str += " ";
  str += "325";

   
   
  p=Form1.bankall(str,out ss);  
  this.textBox1.Text = ss.ToString();
  this.Text = p.ToString();
  }
  }
}

------解决方案--------------------
刚想到一个问题,C++的字符串以'\0'作为结束标识,使用StringBuilder须保证response的内容内无0x00,否则固定长度缓冲区应使用Byte[](同样不需要out或者ref,但调用前要使用new创建足够大的数组)