簡體   English   中英

Delphi和C / C ++ DLL結構與記錄

[英]Delphi and C/C++ DLL Struct vs.Record

我之前曾問過有關delphi和C / C ++ DLL的問題。

我現在還有一個關於記錄/結構的問題。 DLL應該能夠從MainAPP動態更改指針變量的值。

我的delphi MAINAPP有以下記錄:

type MyRec = record
 MyInteger    : Pointer;
 MyWideString : pwidechar;
 MyString     : pchar;
 MyBool       : Pointer
end;

type
 TMyFunc = function ( p  : pointer ): pointer; stdcall;

procedure test;
var
 MyFunction  : TMyFunc;
 TheRecord   : MyRec;
 AnInteger   : Integer;
 AWideString : WideString;
 AString     : String;
 ABool       : Bool;
begin
 AnInteger                := 1234;
 AWideString              := 'hello';
 AString                  := 'hello2';
 ABool                    := TRUE;
 TheRecord.MyInteger      := @AnInteger;
 TheRecord.MyWideString   := pwidechar(AWideString);
 TheRecord.AString        := pchar(AString);
 TheRecord.ABool          := @ABool;
 [...]
 @MyFunction := GetProcAddress...
 [...]
 MyFunction  (@TheRecord);  // now the DLL should be able to change the values dynamically.
 MessageBoxW (0, pwidechar(AWideString), '', 0); // Show the results how the DLL changed the String to...
end;

C / C ++代碼(僅作為示例)

typedef struct _TestStruct{
void    *TheInteger;    // Pointer to Integer
wchar_t *TheWideString; // Pointer to WideString
char    *TheAnsiString; // Pointer to AnsiString  
bool    *TheBool        // Pointer to Bool
}TestStruct;

__declspec(dllexport) PVOID __stdcall MyExportedFunc (TestStruct *PTestStruct)
{
MessageBoxW(0 ,PTestStruct->TheWideString, L"Debug" , 0); // We read the value.
    PTestStruct->TheWideString = L"Let me change the value here.";
return 0;
}

由於某些原因,它會崩潰等。我該怎么辦?

感謝幫助。

在C ++代碼分配給TheWideString指針時,這可能不是崩潰的原因,但是我確實看到了預期的問題...

我注意到您正在將Delphi AWideString變量指向的字符串數據的地址放入記錄的MyWideString字段中。 您將記錄傳遞給C ++函數,該函數將新的指針值分配給記錄的TheWideString/MyWideString字段。 當執行返回到Delphi代碼時,您將輸出AWideString變量的內容。

您的評論表明您希望C ++函數會更改AWideString變量的內容,但事實並非如此。

C ++函數更改結構中的字段。 它對該字段先前指向的存儲位置沒有任何作用。 AWideString指向的數據將不受C ++函數的影響。

如果C ++代碼將數據復制到字段中包含的地址中,則它將覆蓋AWideString指向的字符串數據。 由於AWideString是由Delphi管理的字符串,並且C ++函數將向該字符串存儲區復制比原始字符串已分配空間更多的數據,因此在C ++函數中復制數據將寫入Delphi分配的字符串緩沖區的末尾,並且可能破壞Delphi堆。 稍后可能會發生崩潰。 因此,僅將指針分配給該字段,而不復制數據是一件好事! ;>

若要查看C ++函數發生了什么變化,在調用C ++函數之后,您的Delphi代碼應輸出記錄的MyWideString字段的內容。

同步結構中的字段順序。 您可以使用錯誤的指針破壞內存堆。 另外,請檢查Delphi和C ++中的對齊方式。

您管理的字符串字段不正確。 PWideCharPChar 是不一樣的東西“指針WideString的”和“指針AnsiString類型”。 PWideString Delphi具有PWideStringWideString* )和PAnsiStringAnsiString* )類型。 您還應該使用Delphi的PIntegerint* )和PBooleanbool* )類型,而不是Pointervoid* )。 Delphi和C ++都是類型安全的語言。 盡可能遠離無類型的指針,您的代碼會更好。

type
  PMyRec = ^MyRec;
  MyRec = record
    MyInteger    : PInteger;
    MyWideString : PWideString;
    MyAnsiString : PAnsiString;
    MyBool       : PBoolean;
  end;

  TMyFunc = function ( p  : PMyRec ): Integer; stdcall;

procedure test;
var
  MyFunction  : TMyFunc;
  TheRecord   : MyRec;
  AnInteger   : Integer;
  AWideString : WideString;
  AAnsiString : AnsiString;
  ABool       : Bool;
begin
 AnInteger                := 1234;
 AWideString              := 'hello';
 AAnsiString              := 'hello2';
 ABool                    := TRUE;
 TheRecord.MyInteger      := @AnInteger;
 TheRecord.MyWideString   := @AWideString;
 TheRecord.MyAnsiString   := @AAnsiString;
 TheRecord.MyBool         := @ABool;
 [...]
 @MyFunction := GetProcAddress...
 [...]
 MyFunction  (@TheRecord); 
 MessageBoxW (0, PWideChar(AWideString), '', 0);
end;

typedef struct _MyRec
{
    int        *MyInteger;    // Pointer to Integer
    WideString *MyWideString; // Pointer to WideString
    AnsiString *MyAnsiString; // Pointer to AnsiString  
    bool       *MyBool;       // Pointer to Bool
} MyRec, *PMyRec;

__declspec(dllexport) int __stdcall MyExportedFunc (PMyRec PRec)
{
    MessageBoxW(NULL, PRec->MyWideString->c_bstr(), L"Debug" , 0);
    *(PRec->MyWideString) = L"Let me change the value here.";
    return 0;
}

話雖這么說,跨這樣的DLL邊界操作AnsiString (和UnicodeString )值是非常危險的,特別是如果由於RTL差異,內存管理器差異而使EXE和DLL是在不同版本的Delphi / C ++ Builder中編寫的話,有效負載布局差異等。不過, WideString可以通過,因為它的內存和布局由操作系統而不是RTL控制。

暫無
暫無

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

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