正确将字节从C ++转换为delphi AnsiString

时间:2012-02-01 15:08:17

标签: c# c++ delphi interop data-conversion

我有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 ++开始,如果在SetString上提供AV。

请帮助我。


来自RredCat:

让我为Yuriy的问题添加一些解释: 首先是我们使用的语言。我们需要在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);
}

2 个答案:

答案 0 :(得分:5)

您的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));

是一样的。

答案 1 :(得分:1)

您正在使这项任务变得更加复杂。当您拥有现有的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代码中更喜欢它。