Это исходный код:
Код: Выделить всё
using System.Runtime.InteropServices;
using System.Windows;
namespace DNNETests
{
public class Class1
{
[UnmanagedCallersOnly]
public static void Attach()
{
MessageBox.Show("Hallo c# debugger");
}
[StructLayout(LayoutKind.Sequential)]
public struct IsInputFileVersionCompatibleResult
{
public int resultCode;
public IntPtr msg;
public IntPtr mostRecentRelatedPPPVersion;
}
[UnmanagedCallersOnly]
public static IntPtr Test(int version, IntPtr pstr1, IntPtr pstr2, int version2)
{
string str1 = Marshal.PtrToStringBSTR(pstr1) ?? string.Empty;
string str2 = Marshal.PtrToStringBSTR(pstr2) ?? string.Empty;
MessageBox.Show("parameter: " + version+Environment.NewLine+
str1+Environment.NewLine+
str2+Environment.NewLine+
version2);
return Marshal.StringToBSTR("return value");
}
}
}
< /code>
, и у меня есть приложение Delphi, потребляющее DLL: < /p>
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs;
type
PAttachToDLL = procedure();
PTest = function(version : Integer; str1: WideString; str2 : PWideString; version2 : integer):WideString;
TForm1 = class(TForm)
procedure FormCreate(Sender: TObject);
private
dllAttachToDLL: PAttachToDLL;
dllTest : PTest;
procedure makeTestCall;
public
{ Public-Deklarationen }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.FormCreate(Sender: TObject);
var
dllhandle: THandle;
begin
dllhandle := SafeLoadLibrary('C:\path\to\DNNETests\bin\Debug\net8.0-windows7.0\DNNETestsNE.dll');
@dllAttachToDLL := GetProcAddress(dllhandle, 'Attach');
@dllTest := GetProcAddress(dllhandle, 'Test');
dllAttachToDLL();
makeTEstCall();
Application.Terminate();
end;
procedure TForm1.makeTestCall();
var
tmp:WideString;
ptmp : PWideString;
str1 : WideString;
str2 : WideString;
begin
str1:=WideString('normal widestring');
str2:=WideString('and here pwidestring');
// ptmp:=dllTest(8, str1, PWideString(str2), 7);
tmp:=dllTest(8, (str1), PWideString(str2), 7);
tmp:=WideString(ptmp);
ShowMessage(tmp);
end;
end.
Имя переменной < /th>
value < /th>
Тип данных < /th>
< /tr >
< /thead>
версия < /td>
1375376 < /td>
int < /td>
< /tr>
pstr1 < /td>
0x00000000000008 < /td>
system.intptr
< /tr>
pstr2 < /td>
0x00000000043e73c8 < /td >
system.intptr
< /tr>
version2 < /td>
71189672 < /td>
int < /td>
< /tr>
marshal.ptrtostringbstr(pstr1)
''marshal.ptrtoStringBStr(pstr1) 'бросить исключение Type' System.NullReferenceException '
String {System.NullReferenceExexception}
tr>
функциональный /td>
Теперь я изменяю тип возврата в Delphi на Pwidestring вместо WealString ptest = function (версия: Integer; Str1: WideString; Str2: Pwidestring; Версия2: Integer): pwidestring;
Параметры правильно переносятся в C#
< Таблица класс = "s-table">
Имя переменной < /th>
value < /th>
Тип данных < /th>
< /tr>
< /thead>
версия < /td>
8 < /td>
int < /td>
< /tr>
pstr1 < /td>
0x0000000003259a88 < /td>
system.intptr
< /tr>
< td> pstr2 < /td>
0x0000000003257f98 < /td>
функции >систем.intptr
< /tr>
версия2 < /td>
7 < /td>
int < /td>
< /tr>
marshal.ptrtoStringbStr(pstr1)
"Нормальное расширение" < /td>
string < /td>
< /tr >
marshal.ptrtostringbstr(pstr2)
"и здесь pwidestring" < /td>
String < /td>
< /tr>
< /tbody>
< /table> < /div>
Вопрос: зачем мне объявить тип возврата функции как pwidestring и не только в виде оптимизации и почему мне не нужно отправлять параметры строк от Delphi в C# как pwidestring также? (Что касается двух параметров STR , один из них - Pwidestring Другой WideString )
Подробнее здесь: https://stackoverflow.com/questions/793 ... of-strings
Мобильная версия