簡體   English   中英

從C#調用delphi dll

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM