1
votes

I'm trying to call a DLL built with Delphi 7 (before unicode support) using Delphi XE2. The code is like this:

function Foo(Param1: PChar; Var Param2: DWORD; Var Param3: DWORD): PChar; stdcall; external 'bar.dll';

Then I call:

var
  V1: PChar;
  V2: AnsiString;
  V3, V4: DWORD;

begin
  V1 := Foo(PChar(V2), V3, V4);
  ..

This code works in Delphi 2010 but in XE2 I get an access violation with the following stack:

System.UTF8ToUnicodeString(nil)
System.UTF8ToString(nil)
System.TObject.ClassName
Vcl.Forms.IsClass(???,Exception)
Vcl.Forms.TApplication.HandleException($2083120)
Vcl.Controls.TWinControl.MainWndProc(???)
System.Classes.StdWndProc(726196,273,6106,2365402)
:776e77d8 ; C:\Windows\SysWOW64\user32.dll
:776e78cb ; C:\Windows\SysWOW64\user32.dll
:776ef139 ; C:\Windows\SysWOW64\user32.dll
:776eaaa6 user32.SendMessageW + 0x52
:749fb322 ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.9200.16579_none_8937eec6860750f5\comctl32.dll
:749fb27e ; C:\Windows\WinSxS\x86_microsoft.windows.common-controls_6595b64144ccf1df_6.0.9200.16579_none_8937eec6860750f5\comctl32.dll
:776e77d8 ; C:\Windows\SysWOW64\user32.dll
:776e78cb ; C:\Windows\SysWOW64\user32.dll
:776ebd11 user32.ChangeWindowMessageFilterEx + 0x71
:776ebd39 user32.CallWindowProcW + 0x1c
Vcl.Controls.TWinControl.DefaultHandler(???)
:0048b0c1 TWinControl.DefaultHandler + $DD
:0048afc4 TWinControl.WndProc + $5B8
:0049d031 TButtonControl.WndProc + $71
:004535f2 StdWndProc + $16
:776e77d8 ; C:\Windows\SysWOW64\user32.dll
:776e78cb ; C:\Windows\SysWOW64\user32.dll
:776e899d ; C:\Windows\SysWOW64\user32.dll
:776e8a66 user32.DispatchMessageW + 0x10
2

2 Answers

6
votes

PChar maps to PAnsiChar in D7, but maps to PWideChar in D2009 and later. You are on the right track using AnsiString instead of UnicodeString, but you cannot type-cast an AnsiString to a PWideChar. You need to type-cast it to a PAnsiChar instead, and you need to change your DLL function declaration in D2009+ to match the PAnsiChar that the DLL is actually using:

function Foo(Param1: PAnsiChar; var Param2: DWORD; var Param3: DWORD): PAnsiChar; stdcall; external 'bar.dll';

var
  V1: PAnsiChar;
  V2: AnsiString;
  V3, V4: DWORD;
begin
  V1 := Foo(PAnsiChar(V2), V3, V4);
  ..
3
votes

Being an AnsiString, it is an error to type-cast V2 to PChar in any Delphi version since Delphi 2009. That's when PChar became an alias for PWideChar instead of PAnsiChar. If that code works in Delphi 2010, then it's entirely by accident. Fix your code to use the correct character types.

In Delphi 7, that PChar parameter is PAnsiChar, so change the declaration in your Delphi 2010 and Delphi XE2 import units so that it's explicitly a PAnsiChar. Likewise for the return type.