簡體   English   中英

Delphi和C ++結構

[英]Delphi and c++ struct

我有以下C ++函數,該函數導出其中帶有char*字段的結構,但是在Delphi中使用該字符串值時,盡管它是空終止的,但與預期的不一樣。

typedef struct _MyStruct{
    char* name;
    // other fields
}MyStruct,*PMyStruct;

extern "C" __declspec(dllexport) __cdecl MyTestStr(PMyStruct _PMyStruct)
{
    std::string str = "string";
    std::vector<char> cstr(str.begin(), str.end);
    cstr.push_back('\0');//null-terminated
    _PMyStruct->name = cstr.data();    
}
type
  PMyStruct = ^MyStruct;
  MyStruct= record
    name : PAnsiChar;
        // other fields
  end;

procedure MyTestStr(_PMyStruct: PMyStruct); cdecl; external 'mytest.dll' name 'MyTestStr';    

procedure TestMyRec();
var
  _MyStruct: MyStruct;
begin
  MyTestStr(@_MyStruct); 
  showmessage(_MyStruct.name);
  // here the result is just 'YYYYYYYYYYYYYYYYYY' not 'string'
end;

_PMyStruct->name=cstr.data(); 只是使指針指向字符串體。 但是在函數調用之后,應該處置本地對象 std::string 因此,您已經獲得了指向某個具有不可預測內容的內存地址的指針,如果內存不屬於應用程序,則可能會導致AV。

似乎您必須分配內存並調用將所需數據復制到此內存地址的函數。 需要時釋放此內存。

_MyStruct::name的定義更改為const char * ,並為其分配文字。

請注意,以_開頭並以大寫字母開頭的名稱是為實現保留的,因此您的整個程序都具有未定義的行為。

您不需要typedef struct

struct MyStruct
{ 
    const char* name; // mutable pointer to constant char(s)
    // other fields
};

using PMyStruct = * MyStruct;

extern "C" __declspec(dllexport) __cdecl void MyTestStr(PMyStruct pMyStruct)
{
    pMyStruct->name = "string";
}

在一般情況下,不建議跨dll邊界傳遞擁有的指針。 相反, 調用者應該分配 ,並且函數將復制到該分配中。 這是Win32Api上使用的模式。 您可以返回大小,也可以使用int *參數將大小寫入

C ++ Dll

extern "C" __declspec(dllexport) __cdecl void MyTestStr(PMyStruct pMyStruct = nullptr, int * firstname_size = nullptr, int * lastname_size = nullptr)
{
    if (pMyStruct)
    {
        std::strncpy(pMyStruct->firstname, "string", pMyStruct->firstname_len);
        std::strncpy(pMyStruct->lastname, "other string", pMyStruct->lastname_len);
    }
    if (firstname_size) { *firstname_size = 7; }
    if (lastname_size) { *lastname_size = 13; }
}

德爾福

type
  PInteger = ^Integer;
  PMyStruct = ^MyStruct;
  MyStruct= record
    firstname : PAnsiChar;
    firstname_len : Integer;
    lastname : PAnsiChar;
    lastname_len : Integer;
    // other fields
  end;

procedure MyTestStr(pMyStruct: PMyStruct; firstname_len : PInteger; lastname_len : PInteger); cdecl; external 'mytest.dll' name 'MyTestStr';   

procedure TestMyRec();
var
  myStruct: MyStruct;
begin
// If you don't know how much memory you will need, you have to ask
  MyTestStr(nil, @myStruct.firstname_len, @myStruct.lastname_len); 
  GetMem(myStruct.firstname, myStruct.firstname_len);
  GetMem(myStruct.lastname, myStruct.lastname_len);

  MyTestStr(@myStruct); 

  // Use myStruct

  FreeMem(myStruct.firstname);
  FreeMem(myStruct.lastname);
end;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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