我有一个像这样定义的Delphi dll:
TMPData = record
Lastname, Firstname: array[0..40] of char;
Birthday: TDateTime;
Pid: array[0..16] of char;
Title: array[0..20] of char;
Female: Boolean;
Street: array[0..40] of char;
ZipCode: array[0..10] of char;
City: array[0..40] of char;
Phone, Fax, Department, Company: array[0..20] of char;
Pn: array[0..40] of char;
In: array[0..16] of char;
Hi: array[0..8] of char;
Account: array[0..20] of char;
Valid, Status: array[0..10] of char;
Country, NameAffix: array[0..20] of char;
W, H: single;
Bp: array[0..10] of char;
SocialSecurityNumber: array[0..9] of char;
State: array[0..2] of char;
end;
function Init(const tmpData: TMPData; var ErrorCode: integer; ResetFatalError: boolean = false): boolean;
procedure GetData(out tmpData: TMPData);
我目前的c#签名如下所示:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TMPData
{
[MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
public string Lastname;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
public string Firstname;
[MarshalAs(UnmanagedType.R8)]
public double Birthday;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 16)]
public string Pid;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
public string Title;
[MarshalAs(UnmanagedType.Bool)]
public bool Female;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
public string Street;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 10)]
public string ZipCode;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
public string City;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
public string Phone;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
public string Fax;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
public string Department;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
public string Company;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 40)]
public string Pn;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 16)]
public string In;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 8)]
public string Hi;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
public string Account;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 10)]
public string Valid;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 10)]
public string Status;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
public string Country;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 20)]
public string NameAffix;
[MarshalAs(UnmanagedType.I4)]
public int W;
[MarshalAs(UnmanagedType.I4)]
public int H;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 10)]
public string Bp;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 9)]
public string SocialSecurityNumber;
[MarshalAs(UnmanagedType.LPStr, SizeConst = 2)]
public string State;
}
[DllImport("MyDll.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool Init(TMPData tmpData, int ErrorCode, bool ResetFatalError);
[DllImport("MyDll.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetData(out TMPData tmpData);
我首先调用Init设置BirthDay,LastName和FirstName。然后我调用GetData,但我得到的TMPData结构不正确。将填充FirstName,LastName和Birthday字段,但数据不正确。映射是否正确? (“array [0..40] of char”等于“[MarshalAs(UnmanagedType.LPStr,SizeConst = 40)]”)?
更新
我已经使用反馈更新了c#映射,如下所示:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TMPData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Lastname;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Firstname;
[MarshalAs(UnmanagedType.R8)]
public double Birthday;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string Pid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Title;
[MarshalAs(UnmanagedType.Bool)]
public bool Female;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Street;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string ZipCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string City;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Phone;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Fax;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Department;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Company;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Pn;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string In;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string Hi;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Account;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string Valid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string Status;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Country;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string NameAffix;
[MarshalAs(UnmanagedType.I4)]
public int W;
[MarshalAs(UnmanagedType.I4)]
public int H;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string Bp;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string SocialSecurityNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
public string State;
}
Init函数:
[DllImport("MyDll.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool Init(TMPData tmpData, int ErrorCode, bool ResetFatalError);
现在因以下错误而失败:
“尝试读取或写入受保护的内存。这通常表示其他内存已损坏。
当我打电话给它时如下所示:
int errorCode = 0;
bool resetLastError = true;
TMPData tmpData = new TMPData();
tmpData.Lastname = "TestLastName";
tmpData.Firstname = "TestName";
tmpData.Birthday = 28856.0;
tmpData.Pid = "12345678";
tmpData.Title = null;
tmpData.Female = false;
tmpData.Street = null;
tmpData.ZipCode = null;
tmpData.City = null;
tmpData.Phone = null;
tmpData.Fax = null;
tmpData.Department = null;
tmpData.Company = null;
tmpData.Pn = null;
tmpData.In = null;
tmpData.Hi = null;
tmpData.Account = null;
tmpData.Valid = null;
tmpData.Status = null;
tmpData.Country = null;
tmpData.NameAffix = null;
tmpData.W = 0;
tmpData.H = 0;
tmpData.Bp = null;
tmpData.SocialSecurityNumber = 0;
tmpData.State = null;
bool success = Init(tmpData, errorCode, resetLastError);
如果我在结构定义中将ByValTStr更改为LPStr,则Init函数成功,但GetData函数返回不正确的字符串值。如果我将LPStr更改回ByValTStr,则Init函数会失败,但GetData函数会返回正确的字符串。我不确定我是否应该将char的数组[0..x]编组为ByValTStr的LPStr?
答案 0 :(得分:1)
好吧我终于搞定了。谢谢你的帮助。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)]
public struct TMPData
{
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Lastname;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Firstname;
[MarshalAs(UnmanagedType.R8)]
public double Birthday;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string Pid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Title;
[MarshalAs(UnmanagedType.Bool)]
public bool Female;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Street;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string ZipCode;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string City;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Phone;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Fax;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Department;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Company;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 41)]
public string Pn;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 17)]
public string In;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 9)]
public string Hi;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Account;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string Valid;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string Status;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string Country;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 21)]
public string NameAffix;
[MarshalAs(UnmanagedType.R4)]
public int W;
[MarshalAs(UnmanagedType.R4)]
public int H;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 11)]
public string Bp;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
public string SocialSecurityNumber;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 3)]
public string State;
}
[DllImport("MyDll.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool Init(ref TMPData tmpData,ref int ErrorCode, bool ResetFatalError);
[DllImport("MyDll.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetData(ref TMPData tmpData);
答案 1 :(得分:0)
正如dtb在评论中提到的,0..40是41个字符,而不是40个。显然你的所有字符串定义都没有考虑到第0个元素。
另外,如果我正确阅读,(我不知道C#,但我知道C,)看起来你将char
数组定义为指向long(Unicode,16位)每个字符串)。这有两个潜在的问题。首先,声明这种方式的char数组不是指向字符串的指针,它是一个内联字符串。其次,如果使用Delphi 2009或更高版本构建,它只是一个WideChars数组(每个字符16位)。否则,它是一个Ansi数组(每个字符8位)字符。
答案 2 :(得分:0)
使用什么版本的Delphi构建DLL? Delphi 2009引入了 Unicode ,这意味着你需要在C#中使用Unicode字符串类型,而如果它是在Delphi 2009之前,那么就没有Unicode。 LPStr为8位,而 ByValTStr 的字符类型由应用于包含的System.Runtime.InteropServices.StructLayoutAttribute的System.Runtime.InteropServices.CharSet参数确定。结构
请参阅:http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.unmanagedtype.aspx
你原来说你收到了数据,但这是不正确的。怎么不对?垃圾,还是只是交换,截断等?