楼主,你第一个结构体最后那个数组有问题吧: pPosItems ItemsInfo[XXX]; // Vendors need to decide XXX是什么意思?
楼主,你那样转换错的太多了,我暂且把第一个结构体的最后一句当成这样:PosItems ItemsInfo[2];完整解决: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct Pos { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)] public String POSID; public char TransactionType;TransactionType [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)] public String TransactionNumber; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)] public String TransactionDate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)] public String TransactionTime; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 31)] public String CashierName; public Int32 SiteID; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] public String SiteName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)] public String NozzleNum; public Int32 ItemCount; public Single TotalAmount; public Single InvoiceAmount; public Single DiscountAmount; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] public String Extra1; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] public String Extra2; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] public String Extra3; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)] public PosItems[] ItemsInfo; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct PosItems { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public String ItemCode; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] public String ItemName; public Single ItemQuantity; public Single UnitPrice; public Single ItemAmount; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] public String Extra1; } 函数映射: [DllImport("invoice.dll", EntryPoint="Tax_Invoice",CharSet = CharSet.Ansi)] public static extern int Tax_Invoice(ref Pos val);//不知你为何突然变成PosInvoice ,让人不可思议!
非常感谢sdl2005lyx !!!!! 正在测试中
各位大虾现在的问题是这样的 C#结构定义已经改为: public struct Pos { [MarshalAs(UnmanagedType.ByValTStr,SizeConst=3)] public string POSID;//2+1 POS机编号
public char TransactionType;// 交易类型 S Sale R Return
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=11)] public string TransactionNumber;//10+1 交易流水号
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=9)] public string TransactionDate;//8+1 打印日期CCYYMMDD
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=7)] public string TransactionTime;//6+1 打印时间HHMMSS
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=31)] public string CashierName;//30+1 收银员
public Int32 SiteID;// 加油站编码
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)] public string SiteName;//40+1 加油站名称
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=5)] public string NozzleNum;//4+1 油枪号
public Int32 ItemCount;// 商品项目数量
public Single TotalAmount;// 应收金额 public Single InvoiceAmount;// 实收金额 public Single DiscountAmount;// 优惠金额
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)] public string Extra1;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)] public string Extra2;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)] public string Extra3;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=1)] public PosItems[] ItemsInfo;//明细数据
} [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] public struct PosItems { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] public string ItemCode;//15+1 商品编码
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)] public string ItemName;//40+1 商品名称
public Single ItemQuantity;// 商品数量 public Single UnitPrice;// 商品单价 public Single ItemAmount;// 商品小计金额
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)] public string Extra1;//20+1 备用1 } 现在的问题是如何为Pos及PosItems赋值?如何调用C++中定义的Tax_Invoice (Pos *pPos)??我现在是如下操作的: public Pos makeval() { Pos reval = new Pos();
reval.Extra2 = new byte[41]; reval.Extra3 = new byte[41];
#region 商品明细_开始 PosInvoiceItemsA[] item = new PosInvoiceItemsA[1];//明细数据
item[0].ItemCode = new byte[16]; Array.Copy(this.String2Bytes("16898"),item[0].ItemCode,this.String2Bytes("16898").Length); item[0].ItemName = new byte[41]; Array.Copy(this.String2Bytes("商品名称"),item[0].ItemName,this.String2Bytes("商品名称").Length);
首先得定义结构体长度
其次应该把结构体转化成byte数组
此文章已看过,对我有一些帮助(比如:[MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
),但我这里的C++定义的数据结构是struct内包含struct的,比较复杂。我正在调整、测试中,但还是想请大虾们出手帮帮忙!!
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct Pos
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
public String POSID;
public char TransactionType;TransactionType
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public String TransactionNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public String TransactionDate;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 7)]
public String TransactionTime;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 31)]
public String CashierName;
public Int32 SiteID;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public String SiteName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 5)]
public String NozzleNum;
public Int32 ItemCount;
public Single TotalAmount;
public Single InvoiceAmount;
public Single DiscountAmount;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public String Extra1;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public String Extra2;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public String Extra3;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 2)]
public PosItems[] ItemsInfo;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PosItems
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public String ItemCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public String ItemName;
public Single ItemQuantity;
public Single UnitPrice;
public Single ItemAmount;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public String Extra1;
} 函数映射:
[DllImport("invoice.dll", EntryPoint="Tax_Invoice",CharSet = CharSet.Ansi)]
public static extern int Tax_Invoice(ref Pos val);//不知你为何突然变成PosInvoice ,让人不可思议!
正在测试中
C#结构定义已经改为: public struct Pos
{
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=3)]
public string POSID;//2+1 POS机编号
public char TransactionType;// 交易类型 S Sale R Return
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=11)]
public string TransactionNumber;//10+1 交易流水号
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=9)]
public string TransactionDate;//8+1 打印日期CCYYMMDD
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=7)]
public string TransactionTime;//6+1 打印时间HHMMSS
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=31)]
public string CashierName;//30+1 收银员
public Int32 SiteID;// 加油站编码
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)]
public string SiteName;//40+1 加油站名称
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=5)]
public string NozzleNum;//4+1 油枪号
public Int32 ItemCount;// 商品项目数量
public Single TotalAmount;// 应收金额
public Single InvoiceAmount;// 实收金额
public Single DiscountAmount;// 优惠金额
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)]
public string Extra1;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)]
public string Extra2;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)]
public string Extra3;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=1)]
public PosItems[] ItemsInfo;//明细数据
} [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PosItems
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string ItemCode;//15+1 商品编码
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string ItemName;//40+1 商品名称
public Single ItemQuantity;// 商品数量
public Single UnitPrice;// 商品单价
public Single ItemAmount;// 商品小计金额
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Extra1;//20+1 备用1
}
现在的问题是如何为Pos及PosItems赋值?如何调用C++中定义的Tax_Invoice (Pos *pPos)??我现在是如下操作的: public Pos makeval()
{
Pos reval = new Pos();
reval.POSID = "12";// = POSID// POS机编号
reval.TransactionType = 'S';// 交易类型
reval.TransactionNumber = "12345678";// 交易流水号
reval.TransactionDate = "20090603";// 打印日期
reval.TransactionTime = "130721";//打印时间
reval.CashierName = "收银";//收银员
reval.SiteID = 100;
reval.SiteName = "站点名称";
reval.NozzleNum = "1234";
reval.ItemCount = 1;// 商品项目数量
reval.TotalAmount = 150.00f;// 应收金额
reval.InvoiceAmount = 120.00f;// 实收金额
reval.DiscountAmount = 30.00f;// 优惠金额 reval.Extra1 = "备注1";
reval.Extra2 = "";
reval.Extra3 = "";
#region 商品明细_开始 PosItems[] item = new PosItems[1];//明细数据
item[0].ItemCode = "12345";//vItemCode;
item[0].ItemName = "商品名称";//vItemName;
item[0].ItemQuantity = 30.0f;
item[0].UnitPrice = 50.0f;
item[0].ItemAmount = 150.0f;
item[0].Extra1 = "备注1明细";
#endregion 商品明细_结束
reval.ItemsInfo = new PosInvoiceItemsA[1];//为Pos中的PosItems初始化并赋值
reval.ItemsInfo[0] = item[0]; return reval;
}
调用方法改为: [DllImport("auto_invoice.dll", EntryPoint="Tax_Invoice",CharSet = CharSet.Ansi)]
static extern int Tax_Invoice(ref Pos val); void Button1Click(object sender, System.EventArgs e)
{
Pos pPos = new Pos();
pPos = this.makeval();
i = MainForm.Tax_Invoice(ref pPos);
}
调用时报错
1、“去掉了 *pPos”,这个没有任何关系和影响,判断调用只关心两边的结构体大小和顺序是否一致,别名无关紧要!2、用IntPtr当然可以,只是增加解析复杂度,要用到Marshal类进行转换!对应有明确类型定义的数据结构,参数封送直接用具体类型为好!除非碰到void*这种类型,必须使用IntPtr。3、“ [MarshalAs(UnmanagedType.ByValArray,SizeConst=1)]
public PosItems[] ItemsInfo;//明细数据”
如果你这里只用到1个成员,就不要定义为数组,直接用成员变量即可!
但是你的C++代码:pPosItems ItemsInfo[XXX]; // Vendors need to decide
让人无法判断!4、其实这个结构体并不怎么复杂,只有成员很多而已!这样容易是开发人员犯简单错误。经常会出现调用错误:试图读写受保护的内存!大多由两边结构不一致导致!对付这种问题,一个最直接的方法:在C++那边用sizeof()看看大小为多少!
在C#这部用Marshal.Sizof(Type)看看大小为多少!
发现两边大小不一致,楼主你就仔细检查,一项一项来!别人有时无法代替!
调试器抛出异常 System.AccessViolationException:
尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
[MarshalAs(UnmanagedType.ByValArray,SizeConst=1)]
public PosItems[] ItemsInfo;//明细数据
一、C++中结构定义为 #define POSID_LEN 2 //POSID length
#define TRS_NO_LEN 10 //transaction serial number length
#define CASHIER_NAME_LEN 30 //cashier name length
#define SITENAME_NAME_LEN 40 //site name length
#define NOZZLE_NO_LEN 4 //nozzle number length
#define BACK_UP_LEN 40 //backup field length
#define ITEM_CODE_LEN 15 //item code length
#define ITEM_NAME_LEN 40 //item name length
#define TRS_DATE _LEN 8 //Transaction date length
#define TRS_TIME _LEN 6 //Transaction date length
#define ITEM_BACK_UP_LEN 20 //Item backup field length
typedef struct
{
char POSID[POSID_LEN+1]; //POSID
char TransactionType; //transaction type
char TransactionNumber[TRS_NO_LEN+1];//transaction serial number
char TransactionDate[TRS_DATE _LEN + 1];//transaction date
char TransactionTime[TRS_TIME _LEN + 1];//transaction time
char CashierName[CASHIER_NAME_LEN +1];//cashier name
int SiteID; //site ID
char SiteName[SITENAME_NAME_LEN +1]; //site name
char NozzleNum[NOZZLE_NO_LEN +1]; //nozzle number
int ItemCount; //item count
float TotalAmount; //total amount
float InvoiceAmount; //actual received amount
float DiscountAmount; //discount amount
char Extra1[BACK_UP_LEN + 1]; //backup field
char Extra2[BACK_UP_LEN + 1]; // backup field
char Extra3[BACK_UP_LEN + 1]; // backup field
pPosInvoiceItems ItemsInfo[255]; // Vendors need to decide
} PosInvoice, *pPos;
typedef struct
{
char ItemCode[ITEM_CODE_LEN+1]; //item code
char ItemName[ITEM_NAME_LEN+1]; //item name
float ItemQuantity; //item quantity
float UnitPrice; //unit price
float ItemAmount; //item amount
char Extra1[ITEM_BACK_UP_LEN+1]; //backup field
} PosInvoiceItems, *pPosInvoiceItems; 命令函数:int Tax_Invoice (Pos *pPos)
C#中结构定义为 [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PosInvoice
{
[MarshalAs(UnmanagedType.ByValArray,SizeConst=3)]
public byte[] POSID;//2+1 POS机编号
public char TransactionType;// 交易类型 S Sale R Return
[MarshalAs(UnmanagedType.ByValArray,SizeConst=11)]
public byte[] TransactionNumber;//10+1 交易流水号
[MarshalAs(UnmanagedType.ByValArray,SizeConst=9)]
public byte[] TransactionDate;//8+1 打印日期CCYYMMDD
[MarshalAs(UnmanagedType.ByValArray,SizeConst=7)]
public byte[] TransactionTime;//6+1 打印时间HHMMSS
[MarshalAs(UnmanagedType.ByValArray,SizeConst=31)]
public byte[] CashierName;//30+1 收银员
public Int32 SiteID;// 加油站编码
[MarshalAs(UnmanagedType.ByValArray,SizeConst=41)]
public byte[] SiteName;//40+1 加油站名称
[MarshalAs(UnmanagedType.ByValArray,SizeConst=5)]
public byte[] NozzleNum;//4+1 油枪号
public Int32 ItemCount;// 商品项目数量
public Single TotalAmount;// 应收金额
public Single InvoiceAmount;// 实收金额
public Single DiscountAmount;// 优惠金额
[MarshalAs(UnmanagedType.ByValArray,SizeConst=41)]
public byte[] Extra1;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=41)]
public byte[] Extra2;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=41)]
public byte[] Extra3;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=255)]
public PosInvoiceItems[] ItemsInfo;//明细数据
} [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PosInvoiceItems
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)]
public byte[] ItemCode;//15+1 商品编码
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 41)]
public byte[] ItemName;//40+1 商品名称
public Single ItemQuantity;// 商品数量
public Single UnitPrice;// 商品单价
public Single ItemAmount;// 商品小计金额
// [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 21)]
public byte[] Extra1;//20+1 备用1
}C#中对结构赋值为 public PosInvoiceA makevalA()
{
PosInvoiceA reval = new PosInvoiceA();
reval.POSID = new byte[3];
Array.Copy(this.String2Bytes("29"),reval.POSID,this.String2Bytes("29").Length);
reval.TransactionType = 'S';
reval.TransactionNumber = new byte[11];
Array.Copy(this.String2Bytes("20000009"),reval.TransactionNumber,this.String2Bytes("20000009").Length);
reval.TransactionDate = new byte[9];
Array.Copy(this.String2Bytes("20110711"),reval.TransactionDate,this.String2Bytes("20110711").Length);
reval.TransactionTime = new byte[7];
Array.Copy(this.String2Bytes("161718"),reval.TransactionTime,this.String2Bytes("161718").Length);
reval.CashierName = new byte[31];
Array.Copy(this.String2Bytes("按擦剂威武"),reval.CashierName,this.String2Bytes("按擦剂威武").Length);
reval.SiteID = 100;// 加油站编码
reval.SiteName = new byte[41];
Array.Copy(this.String2Bytes("加油站名称:刘某人的油站"),reval.SiteName,this.String2Bytes("加油站名称:刘某人的油站").Length);
reval.NozzleNum = new byte[5];
Array.Copy(this.String2Bytes("9118"),reval.NozzleNum,this.String2Bytes("9118").Length);
reval.ItemCount = 1;// 商品项目数量
reval.TotalAmount = 123.45f;// 应收金额
reval.InvoiceAmount = 100.12f;// 实收金额
reval.DiscountAmount = 23.33f;// 优惠金额 reval.Extra1 = new byte[41];
Array.Copy(this.String2Bytes("备用1"),reval.Extra1,this.String2Bytes("备用1").Length);
reval.Extra2 = new byte[41]; reval.Extra3 = new byte[41];
#region 商品明细_开始
PosInvoiceItemsA[] item = new PosInvoiceItemsA[1];//明细数据
item[0].ItemCode = new byte[16];
Array.Copy(this.String2Bytes("16898"),item[0].ItemCode,this.String2Bytes("16898").Length); item[0].ItemName = new byte[41];
Array.Copy(this.String2Bytes("商品名称"),item[0].ItemName,this.String2Bytes("商品名称").Length);
item[0].ItemQuantity = 30.0f;
item[0].UnitPrice = 50.0f;
item[0].ItemAmount = Convert.ToSingle(150.0f);
item[0].Extra1 = new byte[21];
Array.Copy(this.String2Bytes("商品备注"),item[0].Extra1,this.String2Bytes("商品备注").Length);
#endregion 商品明细_结束 reval.ItemsInfo = new PosInvoiceItemsA[255];
reval.ItemsInfo[0] = item[0];
return reval;
}C#调用代码为 [DllImport("auto_invoice.dll", EntryPoint="Tax_Invoice",CharSet = CharSet.Ansi)]
static extern int Tax_Invoice(ref PosInvoice val); void Button1Click(object sender, System.EventArgs e)
{
int i = MainForm.Tax_Connection();
if (i==0)
{
i=255;
PosInvoice pPos = new PosInvoice();
pPos = this.makeval();
int k = Marshal.SizeOf(pPos);//24736
i = MainForm.Tax_Invoice(ref pPos);
MessageBox.Show(i.ToString());
}
else
MessageBox.Show("连接失败"+i.ToString()); }
public struct PosInvoice
{
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=3)]
public string POSID;//2+1 POS机编号
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=1)]
public string TransactionType;// 交易类型 S Sale R Return
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=11)]
public string TransactionNumber;//10+1 交易流水号
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=9)]
public string TransactionDate;//8+1 打印日期CCYYMMDD
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=7)]
public string TransactionTime;//6+1 打印时间HHMMSS
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=31)]
public string CashierName;//30+1 收银员
public Int32 SiteID;// 加油站编码
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)]
public string SiteName;//40+1 加油站名称
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=5)]
public string NozzleNum;//4+1 油枪号
public Int32 ItemCount;// 商品项目数量
public Single TotalAmount;// 应收金额
public Single InvoiceAmount;// 实收金额
public Single DiscountAmount;// 优惠金额
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)]
public string Extra1;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)]
public string Extra2;
[MarshalAs(UnmanagedType.ByValTStr,SizeConst=41)]
public string Extra3;
[MarshalAs(UnmanagedType.ByValArray,SizeConst=255)]
public PosInvoiceItems[] ItemsInfo;//明细数据
} [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct PosInvoiceItems
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
public string ItemCode;//15+1 商品编码
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string ItemName;//40+1 商品名称
public Single ItemQuantity;// 商品数量
public Single UnitPrice;// 商品单价
public Single ItemAmount;// 商品小计金额
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Extra1;//20+1 备用1
}