Tôi đã bắt đầu nâng cấp ứng dụng .NET 2.0 WinForms lên .NET 4.0. Vâng, OK, quá trình nâng cấp chỉ là vấn đề chuyển đổi mục tiêu nền tảng, nhưng làm cho nó thực sự hoạt động. Tôi cho rằng đó là tất cả sẽ có nó.Đã P/Invoke thay đổi môi trường trong .NET 4.0?
Nhưng có vẻ như điều gì đó đã thay đổi đáng kể trong .NET 4.0 liên quan đến interop. Sử dụng DllImport(), ứng dụng nhúng một vài tệp dll Delphi. Khi ứng dụng nhắm mục tiêu .NET 2.0, mọi thứ hoạt động bình thường. Nhưng khi tôi thay đổi nó để nhắm mục tiêu .NET 4.0, công cụ bắt đầu đi haywire, giống như một cái gì đó đang làm hỏng bộ nhớ.
Ví dụ: nó thay thế các chữ số duy nhất bằng "0" ở những vị trí lạ. Dữ liệu được truyền trong IStream được thay thế bằng 8 ký tự bằng (Hex) 00 00 00 00 00 00 00 80, nhưng chỉ khoảng 70% thời gian. Hai cuộc gọi liên tiếp để truy lục cùng một giá trị trả lại các kết quả khác nhau (lấy một giá trị từ bộ đệm trong bộ nhớ, thành công lần đầu tiên, không thực hiện lần thứ hai). Các chuỗi được gửi tới nhật ký được hiển thị bị cắt bớt.
Tôi đã thử rất nhiều nội dung cố gắng thực hiện các quy ước gọi điện rõ ràng hơn, không có tác vụ nào có hiệu lực. Tất cả các chuỗi được xử lý như [MarshalAs (UnmanagedType.LPWStr)] ở phía .NET và PWChar ở phía Delphi.
Điều gì đã thay đổi trong .NET 4.0 sẽ phá vỡ P/Gọi như thế này?
---------------------------- Chỉnh sửa ----------------- --------------------
Dưới đây là ví dụ đơn giản nhất. Nó tạo một file PDF mà đôi khi hoạt động chính xác, nhưng thường xuyên hơn kết thúc lên bị hỏng (và hoạt động chính xác trong .NET 2.0):
[DllImport(DLLName)]
public static extern void SetDBParameters(
[MarshalAs(UnmanagedType.LPWStr)] string Server,
[MarshalAs(UnmanagedType.LPWStr)] string Database,
[MarshalAs(UnmanagedType.LPWStr)] string User,
[MarshalAs(UnmanagedType.LPWStr)] string Password,
short IntegratedSecurity);
procedure SetDBParameters(Server, Database, User, Password: PWChar;
IntegratedSecurity: WordBool); stdcall;
[DllImport(DLLName)]
public static extern short GeneratePDF(
[MarshalAs(UnmanagedType.LPWStr)] string Param1,
[MarshalAs(UnmanagedType.LPWStr)] string Param2,
[MarshalAs(UnmanagedType.LPWStr)] string Param3,
[MarshalAs(UnmanagedType.LPWStr)] string Param4,
out IStream PDFData);
function GeneratePDF(Param1, Param2, Param3, Param4: PWChar;
out PDFData: IStream): WordBool; stdcall;
private byte[] ReadIStream(IStream Stream)
{
if (Stream == null)
return null;
System.Runtime.InteropServices.ComTypes.STATSTG streamstats;
Stream.Stat(out streamstats, 0);
Stream.Seek(0, 0, IntPtr.Zero);
if (streamstats.cbSize <= 0)
return null;
byte[] result = new byte[streamstats.cbSize];
Stream.Read(result, (int)streamstats.cbSize, IntPtr.Zero);
return result;
}
WordBool và ngắn ban đầu boolean (Delphi) và bool (C#), tôi đã thay đổi họ để rõ ràng hơn, chỉ trong trường hợp.
---------------------------- Chỉnh sửa ----------------- --------------------
Nội dung tôi đã viết trước đó về WinForms dường như đã không trở nên hoàn toàn phù hợp, tôi đã tạo lại một trong những vấn đề không có giao diện người dùng nào. Chương trình sau tạo ra 0,1,2,3,4,5,6,7,8,9 dưới 2,0/3,5, nhưng 0, -1, -1, -1, -1, -1, -1, - 1, -1 dưới 4.0.
using System;
using System.Runtime.InteropServices;
namespace TestNet4interop
{
static class Program
{
[DllImport("TestSimpleLibrary.dll", PreserveSig=true, CallingConvention = CallingConvention.StdCall)]
public static extern void AddToList(long value);
[DllImport("TestSimpleLibrary.dll", PreserveSig=true, CallingConvention = CallingConvention.StdCall)]
public static extern int GetFromList(long value);
static void Main()
{
for (long i = 0; i < 10; i++)
{
AddToList(i);
Console.WriteLine(GetFromList(i));
}
}
}
}
Và phía bên Delphi (biên soạn với Delphi 2007):
library TestSimpleLibrary;
uses
SysUtils,
Classes;
{$R *.res}
var
List: TStringList;
procedure AddToList(value: int64); stdcall;
begin
List.Add(IntToStr(value));
end;
function GetFromList(value: int64): integer; stdcall;
begin
result := List.IndexOf(IntToStr(value));
end;
exports
AddToList,
GetFromList;
begin
List := TStringList.Create;
end.
Bạn có thể hiển thị chữ ký PInvoke cho chúng tôi không? – JaredPar
Bài đăng này http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/922fa431-5426-48c6-8949-538dfbb2f266 cho thấy rằng bản sửa lỗi đã thay đổi trong 4.0, nhưng không cung cấp danh sách đầy đủ về những gì đã thay đổi. –
Có thể thú vị khi biết: [Visual Studio 2010 SP1] (http://support.microsoft.com/kb/983509) không ** không ** khắc phục sự cố, chúng tôi vừa thử ở đây. –