本帖最后由 liuyongxu 于 2011-09-01 14:41:19 编辑

解决方案 »

  1.   

    记得以前不是这样做的
    首先得定义结构体长度
    其次应该把结构体转化成byte数组
      

  2.   

    bobui您好,能把您以前的代码给我参考一下吗?
      

  3.   

    你的代码太多,自己看看这篇文章吧http://msdn.microsoft.com/zh-cn/library/aa288468%28VS.71%29.aspx
      

  4.   

    http://msdn.microsoft.com/zh-cn/library/aa288468%28VS.71%29.aspx
    此文章已看过,对我有一些帮助(比如:[MarshalAs(UnmanagedType.ByValTStr, SizeConst=LF_FACESIZE)]
    ),但我这里的C++定义的数据结构是struct内包含struct的,比较复杂。我正在调整、测试中,但还是想请大虾们出手帮帮忙!!
      

  5.   

    楼主,你第一个结构体最后那个数组有问题吧:       pPosItems ItemsInfo[XXX];   // Vendors need to decide XXX是什么意思?
      

  6.   

    楼主,你那样转换错的太多了,我暂且把第一个结构体的最后一句当成这样: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 ,让人不可思议!
      

  7.   

    非常感谢sdl2005lyx !!!!!
    正在测试中
      

  8.   

    各位大虾现在的问题是这样的
    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);

    调用时报错
      

  9.   

    我给你一个建议,要求编写c++ dlld的人提供一套经过严格测试的c#类库。否则谁主张用c++谁去实现它。
      

  10.   

    楼主,回答你几个问题:
    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)看看大小为多少!
    发现两边大小不一致,楼主你就仔细检查,一项一项来!别人有时无法代替!
      

  11.   

    现在报错信息为:
    调试器抛出异常 System.AccessViolationException:
    尝试读取或写入受保护的内存。这通常指示其他内存已损坏。
      

  12.   

    十分的混乱。而且你数据结构中的最后一项没有指定大小,如果你不指定大小,那么你应该定义为指针,而不是数组。 C# code
     [MarshalAs(UnmanagedType.ByValArray,SizeConst=1)]
                public PosItems[] ItemsInfo;//明细数据
      

  13.   

    谢谢大家!!!
    一、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()); }
      

  14.   

    测试时还用另一种方式定义为C#中的结构: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    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
    }