[英]calling delphi dll from c#
我有一個這樣定義的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字段已填充,但數據不正確。 映射正確嗎? (“ char的array [0..40]”等於“ [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;
}
初始化函數:
[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的array [0..x]編組為ByValTStr的LPStr?
好吧,我終於開始工作了。 謝謝您的幫助。
[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);
正如dtb在他的評論中提到的,0..40是41個字符,而不是40個字符。顯然您的所有字符串定義都沒有考慮到第0個元素。
另外,如果我沒看錯((我不知道C#,但我確實知道C),則好像您正在將char
數組定義為指向長(Unicode,每個char 16位)字符串的指針。 有兩個潛在的問題。 首先,以這種方式聲明的char數組不是指向字符串的指針,而是內聯字符串。 其次,如果它是使用Delphi 2009或更高版本構建的,則僅是WideChars數組(每個字符16位)。 否則,它是一個Ansi(每個字符8位)字符數組。
DLL使用哪個版本的Delphi? Delphi 2009引入了Unicode ,這意味着您需要在C#中使用Unicode字符串類型,而如果它是在Delphi 2009之前的版本,則沒有Unicode。 LPStr是8 Bit ,而ByValTStr的字符類型由應用於包含結構的System.Runtime.InteropServices.StructLayoutAttribute的System.Runtime.InteropServices.CharSet參數確定。
請參閱: http : //msdn.microsoft.com/zh-cn/library/system.runtime.interopservices.unmanagedtype.aspx
您最初說的是要取回數據,但這是不正確的。 怎么會不正確? 垃圾,還是只是被交換,截斷等等?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.