如题所述,当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(¶m1);//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
//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(¶m1);//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
如果C++Builder用了AnsiString类型,那么有可能会出错
继续ing……
在C++中char是8位。对于仅仅是in类型的char*,通常都可以使用string表示,封送的时候C#会自动处理的。
对于结构中的DataString 变量,你确定C++函数不会修改他吗?如果实在不行,可以使用C++再次对该DLL进行封装,以简化参数
在结构体前加: [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
/// <summary>
/// 要生成图片的字符串
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string DataString;
我在C#中构造一个结构体,这个结构体中我准备使用string代替C++中的char *
DLL的函数中的参数是 &结构体
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);
感谢蓝风和老邱等各位大神。