Delphi和C / C ++ DLL结构体vs.Record [英] Delphi and C/C++ DLL Struct vs.Record

查看:185
本文介绍了Delphi和C / C ++ DLL结构体vs.Record的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我previously问了一个问题关于一个Delphi和C / C ++ DLL。

I previously asked a question about a delphi and a C/C++ DLL.

我现在大概记录/结构的另一个问题。
该DLL应能够动态地改变从MainAPP指针瓦尔的价值。

I have now another question about a record / struct. The DLL should be able to dynamically CHANGE the VALUE of the pointer vars from the MainAPP.

我的德尔福MAINAPP有如下记录:

My delphi MAINAPP has the following record:

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 ++ code(例如只)

C/C++ Code (just example)

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;
}

有关某些原因崩溃等。
我该怎么办错了?

For some reasons it crashes etc. What do I do wrong?

感谢您的帮助。

推荐答案

您是管理不善的字符串字段。 PWideChar PChar类型 不是同样的事情为指针WideString的和指针到AnsiString类型。德尔福 PWideString WideString的* )和 PAnsiString AnsiString类型* )类型的,而不是目的。你也应该用Delphi的 PInteger 为int * )和 PBoolean BOOL * )类型而不是指针无效* )。 Delphi和C ++都是类型安全的语言。远离无类型的指针离开时,可能的话,你的code会变得更好。

You are mismanaging the string fields. PWideChar and PChar are not the same thing as "pointer to WideString" and "pointer to AnsiString". Delphi has PWideString (WideString*) and PAnsiString (AnsiString*) types for that purpose instead. You should also use Delphi's PInteger (int*) and PBoolean (bool*) types instead of Pointer (void*). Delphi and C++ are both type-safe languages. Stay away from untyped pointers when possible, your code will be better for it.

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;
}

随着中说,它可以是非常危险的操作 AnsiString类型(和的Uni codeSTRING )的值整个这样一个DLL边界,特别是如果EXE和DLL都写在由于RTL差别,内存管理器的差异,有效载荷布局的差异等不同的版本的Delphi / C ++ Builder中的 WideString的即可通过身边,虽然,因为它的内存和布局由操作系统控制,而不是RTL。

With that said, it can be very dangerous to manipulate AnsiString (and UnicodeString) values across a DLL boundary like this, especially if the EXE and DLL are written in different versions of Delphi/C++Builder due to RTL differences, memory manager differences, payload layout differences, etc. WideString is OK to pass around, though, because it's memory and layout are controlled by the OS, not the RTL.

这篇关于Delphi和C / C ++ DLL结构体vs.Record的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆