更正从C++到delphi AnsiString的字节转换

Correct converting bytes from C++ to delphi AnsiString

本文关键字:AnsiString 字节 转换 delphi C++      更新时间:2023-10-16

我有一个dll,它接受指向C++字节数组的指针,并尝试以以下方式将这些数据移动到AnsiString中

procedure Convert(const PByteArr: Pointer; ArrSize: Cardinal); export; cdecl;
var
  Buf: AnsiString;
begin
  SetString(Buf, PAnsiChar(PByteArr^), ArrSize);
end;

如果我从Delphi 调用此方法

procedure Try;
var
  M: TMemoryStream;
  Arr: TBytes;  
begin
  M := TMemoryStream.Create;
  try
    M.LoadFromFile('myfile.dat');
    SetLength(Arr, M.Size);
    M.Position := 0;
    M.Read(Arr[0], M.Size);
  finally
    M.Free;
  end;
  Convert(@Arr, Length(Arr));
end;

它工作得很好,但从c++if在SetString上给出AV。

请帮我做这个。


来自RredCat:

让我对尤里的问题补充一些解释:首先是关于我们使用的语言。我们需要在C#项目中调用Delphi dll。为此,我创建了C++\CLI层(代理)。现在介绍头文件中的C++\CLI代码:

HINSTANCE hDelphiDLL;
typedef void (*pPBDFUNC)(byte* aBytes, int size);
pPBDFUNC Convert;

在cpp中,我在构造函数中设置Convert:

hDelphiDLL = LoadLibrary(<path to dll>);
if(NULL != hDelphiDLL ){
    pPBDFUNC clb= GetProcAddress(HMODULE(hDelphiDLL), "Convert");
        if(NULL != clb){
            Convert= pPBDFUNC (clb);
        }...

我从C#调用的最后一个方法:

void Class1::Test(byte* aBytes, int size){
    Convert(aBytes,size);
}

您的Delphi代码传递一个指向字节数组的指针。简化为只使用指向字节数组的指针:

procedure Convert(const PByteArr: Pointer; ArrSize: Cardinal); export; cdecl;
var
  Buf: AnsiString;
begin
  SetString(Buf, PAnsiChar(PByteArr), ArrSize);
end;

并称之为

Convert(@Arr[0], Length(Arr));

Convert(Pointer(Arr), Length(Arr));

这是相同的。

您使这项任务变得比需要的要复杂得多。当您有一个现有的C或C++代码体,或者一个具有非常大接口的本地库时,C++/CLI非常棒。只要您只有少数几个函数,那么直接p/invoke到本地Delphi DLL就是一种方法。

Serg已经指出了Delphi函数中虚假的额外间接级别。所以我会把Delphi函数写成:

procedure TestFunction(Text: PAnsiChar); stdcall;
var
  Buf: AnsiString;
begin
  Buf := Text;
end;

在C#端,您可以这样声明函数:

[DllImport(@"mydll.dll")]
static extern void TestFunction(string Text);

您可以从C#代码中调用此函数,如下所示:

TestFunction("Hello");
string str = GetStringFromSomewhere();
TestFunction(str);

就这样!由于在C#端有一个字符串变量,因此可以依靠p/invoke marshaller为本机代码提供一个以null结尾的字符串。因此,没有必要通过长度。p/invoke的默认调用约定是stdcall,因此更喜欢Delphi代码中的调用约定。