如题所述,当C#中结构体中的一个String变量为空时,返回正确值,当此变量不为空时就没有返回正确值。很郁闷。难道C++结构体中的char * 不是对应C#中的String吗?我sizeof测量的我在C#中定义的结构体的大小和VC++中是一样的?难道是因为内存对齐的原因?等高手,此问题困扰我两天了,谢谢各位。//我用C#调用C++ Build写的DLl时得不到正确返回,我同事使用VC6.0调用此DLL时就可以得到正确的返回,请问这是为何?传递的参数是一个结构体。代码如下:
//c++调用Dll并传递结构体地址:
TSS_Make_Data   *SS_Make_Data;
TReadFromStream *ReadFromStream;
SS_Make_Data = (TSS_Make_Data *)GetProcAddress(Hinst,"SS_Make_Data");
ReadFromStream = (TReadFromStream *)GetProcAddress(Hinst,"ReadFromStream");
if(SS_Make_Data != NULL)
{
nFileLen = SS_Make_Data(&param1);//param1是结构体
                }
//C++ 中的结构体定义:
typedef struct
{
    int     TDH;
    int     Width;
    int     Height;
    int     Effect;
    int     Level;
    int     Speed;
    int     Delay;
    int     DataFont;  //0-row 1-
    int     DataColor;
    char *  FontName;    bool      IsCheckTime;
    char *   StartTime;
    char *   EndTime;
    //----  
    char *  DataString;
} TDataParam;
//C#中的DLL封装:
  public class pArmMMData
    {
        /// <summary>
        /// 将字符串生成图片
        /// </summary>
        /// <param name="t">要生成图片的节目的信息的结构体</param>
        /// <returns>返回生成的字节数组的长度</returns>
        [DllImport("pArmMMData.dll", EntryPoint = "SS_Make_Data")]
        public static extern int SS_Make_Data(ref TDataParam t);
        //           public static extern int SS_Make_Data(TDataParam t);
        /// <summary>
        /// 获取生成的节目的字符数组的长度
        /// </summary>
        /// <param name="SendBuffer">返回的字节数组</param>
        /// <param name="Length">要获取的长度(即SS_Make_Data方法的返回值)</param>
        /// <returns></returns>
        [DllImport("pArmMMData.dll", EntryPoint = "ReadFromStream")]
        public static extern void ReadFromStream(byte[] SendBuffer, int Length);
    }
//C#中的结构体定义
  /// <summary>
    /// 传递给DLL的结构体,标示一个实体的所有信息
    /// </summary>
    public struct TDataParam
    {
        /// <summary>
        /// 节目编号
        /// </summary>
        public int TDH;
        /// <summary>
        /// 宽度
        /// </summary>
        public int Width;
        /// <summary>
        /// 高度
        /// </summary>
        public int Height;
        /// <summary>
        /// 显示效果       
        /// </summary>
        public int Effect;
        /// <summary>
        /// 速度等级 0
        /// </summary>
        public int Level;
        /// <summary>
        /// 显示速度
        /// </summary>
        public int Speed;
        /// <summary>
        /// 停留时间
        /// </summary>
        public int Delay;
        /// <summary>
        /// 字号
        /// </summary>
        public int FontSize;  //0-row 1-
        /// <summary>
        /// 颜色:0-红色,1-绿色,2-黄色
        /// </summary>
        public int DataColor;
        /// <summary>
        /// 字体
        /// </summary>
        public string FontName;
        /// <summary>
        /// 是否有时限
        /// </summary>
        public bool IsCheckTime;
        /// <summary>
        /// 时限-开始时间
        /// </summary>
        public string StartTime;
        /// <summary>
        /// 时限-结束时间
        /// </summary>
        public string EndTime;
        /// <summary>
        /// 要生成图片的字符串
        /// </summary> 
        public string DataString;
    }//C#中的DLL调用:
  TDataParam t = new TDataParam();//定义一个新的结构体实体
            t.DataColor = 0;
            t.DataString = textBox1.Text.Trim();
            t.Delay = 0;
            t.Effect = 15;
            t.EndTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            t.FontName = "宋体";
            t.FontSize = 32;
            t.Height = 32;
            t.IsCheckTime = false;
            t.Level = 0;
            t.Speed = 3;
            t.StartTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
            t.TDH = 1;
            t.Width = 128;
            MessageBox.Show("结构体大小:" + Marshal.SizeOf(t).ToString());//此处返回56和VC++6.0中的sizeof返回值一样
            int ilength = pArmMMData.SS_Make_Data(ref t);//此处调用DLL,返回值为0

解决方案 »

  1.   

    可能是数据类型问题
    如果C++Builder用了AnsiString类型,那么有可能会出错
      

  2.   

    难道C++结构体中的char * 不是对应C#中的String吗?不是这么一回事的,跟你的编码有关系 在C#里面,sbyte才是对应C#里面的char,不过,同样涉及编码格式 
      

  3.   

    现在IntPtr、StringBuild char[]均试过了。失败。
    继续ing……
      

  4.   

    在C#中char是16位。
    在C++中char是8位。对于仅仅是in类型的char*,通常都可以使用string表示,封送的时候C#会自动处理的。
    对于结构中的DataString 变量,你确定C++函数不会修改他吗?如果实在不行,可以使用C++再次对该DLL进行封装,以简化参数
      

  5.   

    你这样写struct不行,还需要用MarshelAs等特性进行修饰
      

  6.   

    我使用这篇博文中的方法封装Struct还是不行
    在结构体前加: [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
    在封装DLL的方法时加: [DllImport("pArmMMData.dll", EntryPoint = "SS_Make_Data", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Ansi)]        
    http://www.cnblogs.com/clingingboy/archive/2010/08/26/1809623.html
      

  7.   

    结构体中的字符串成员已经按照如下 样式添加特性依然得不到正确结果。
     /// <summary>
            /// 要生成图片的字符串
            /// </summary>    
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]        
            public string DataString;
      

  8.   

    那几个char*成员是传入还是传出?如果是传出,内存由谁分配的?
      

  9.   

    那几个char *是传入的。
    我在C#中构造一个结构体,这个结构体中我准备使用string代替C++中的char *
    DLL的函数中的参数是 &结构体
      

  10.   

    把MarshalAs那里多换几种,总有能行的
      

  11.   

    几个地方,你改一下试试:
    1、[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] //指明字符串封送处理方式
    public struct TDataParam{}
    2、  [DllImport("pArmMMData.dll", EntryPoint = "SS_Make_Data"
            ,CallingConvention=CallingConvention.Cdecl) ]   //指明调用约定
            public static extern int SS_Make_Data(ref TDataParam t);
      

  12.   

    原来是内部DLL的问题,传输的一个参数有问题,多谢大石头兄弟两天帮我调试。
    感谢蓝风和老邱等各位大神。