C#调用C++ Build 写的DLL出错,VC6.0调用时却可以返回正确值。

walkghost 2011-07-21 05:03:23
如题所述,当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
...全文
162 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
walkghost 2011-07-22
  • 打赏
  • 举报
回复
原来是内部DLL的问题,传输的一个参数有问题,多谢大石头兄弟两天帮我调试。
感谢蓝风和老邱等各位大神。
sdl2005lyx 2011-07-22
  • 打赏
  • 举报
回复
几个地方,你改一下试试:
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);
呔妖怪来嘛 2011-07-22
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 soaringbird 的回复:]
byte[]
[/Quote]
这个试试
soaringbird 2011-07-22
  • 打赏
  • 举报
回复
把MarshalAs那里多换几种,总有能行的
walkghost 2011-07-22
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 soaringbird 的回复:]

那几个char*成员是传入还是传出?如果是传出,内存由谁分配的?
[/Quote]
那几个char *是传入的。
我在C#中构造一个结构体,这个结构体中我准备使用string代替C++中的char *
DLL的函数中的参数是 &结构体
soaringbird 2011-07-22
  • 打赏
  • 举报
回复
那几个char*成员是传入还是传出?如果是传出,内存由谁分配的?
walkghost 2011-07-22
  • 打赏
  • 举报
回复
结构体中的字符串成员已经按照如下 样式添加特性依然得不到正确结果。
/// <summary>
/// 要生成图片的字符串
/// </summary>
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 255)]
public string DataString;
walkghost 2011-07-21
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 soaringbird 的回复:]

你这样写struct不行,还需要用MarshelAs等特性进行修饰
[/Quote]
我使用这篇博文中的方法封装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
soaringbird 2011-07-21
  • 打赏
  • 举报
回复
你这样写struct不行,还需要用MarshelAs等特性进行修饰
walkghost 2011-07-21
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wangyong0921 的回复:]

难道C++结构体中的char * 不是对应C#中的String吗?

不是这么一回事的,跟你的编码有关系

在C#里面,sbyte才是对应C#里面的char,不过,同样涉及编码格式
[/Quote]
那我改成sbyte[] ?
walkghost 2011-07-21
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 int64 的回复:]

可能是数据类型问题
如果C++Builder用了AnsiString类型,那么有可能会出错
[/Quote]
恩,有这个问题的可能,请问我该如何修改我的C#中的结构体呢?
walkghost 2011-07-21
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 isjoe 的回复:]

在C#中char是16位。
在C++中char是8位。

对于仅仅是in类型的char*,通常都可以使用string表示,封送的时候C#会自动处理的。
对于结构中的DataString 变量,你确定C++函数不会修改他吗?

如果实在不行,可以使用C++再次对该DLL进行封装,以简化参数
[/Quote]
我部能确定C++函数会不会修改它。
第二种方法倒是可以作为备选方案。
感谢你。
soaringbird 2011-07-21
  • 打赏
  • 举报
回复
byte[]
isjoe 2011-07-21
  • 打赏
  • 举报
回复
在C#中char是16位。
在C++中char是8位。

对于仅仅是in类型的char*,通常都可以使用string表示,封送的时候C#会自动处理的。
对于结构中的DataString 变量,你确定C++函数不会修改他吗?

如果实在不行,可以使用C++再次对该DLL进行封装,以简化参数
walkghost 2011-07-21
  • 打赏
  • 举报
回复
现在IntPtr、StringBuild char[]均试过了。失败。
继续ing……
ohkuy 2011-07-21
  • 打赏
  • 举报
回复
我估计是数据类型问题
智能大石头 2011-07-21
  • 打赏
  • 举报
回复
试一试?
Just4life 2011-07-21
  • 打赏
  • 举报
回复
难道C++结构体中的char * 不是对应C#中的String吗?

不是这么一回事的,跟你的编码有关系

在C#里面,sbyte才是对应C#里面的char,不过,同样涉及编码格式
int64 2011-07-21
  • 打赏
  • 举报
回复
可能是数据类型问题
如果C++Builder用了AnsiString类型,那么有可能会出错

110,538

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧