3
votes

I need to wrap some legacy code in Delphi 7 for use within Delphi XE2. My question seems simple, but I tried ALL the examples I could find and they all fail. Basically, I need to be able to pass strings between D7 and DXE2, and as far as I can figure out, the safest approach is to use pchar (since I do not want to ship the borlandmm dll). So DLL written in D7, to be called by Delphi XE2

My interface needs to be

IN My DLL:

function d7zipFile(pFatFile,pThinFile : PChar) : integer; stdCall;
function d7unzipfile(pThinFile,pFatFile : PChar) : integer; stdCall;

I need to pass BACK the pFatFile name in the unzipfile function.

In My calling code:

function d7zipFile(pFatFile,pThinFile : PChar) : integer; external 'd7b64zip.dll';

function d7unzipfile(pThinFile,pFatFile : PChar) : integer; external 'd7b64zip.dll';

Could someone please assist with the best way to implement these?

Obviously I am not looking for the actual zip/unzip code - I have that working fine within D7. I want to know how to declare and work with the string / pchar params, since the various types I tried (PWideChar, WideString, ShortString etc) all give errors.

So I would be happy to simply be able to do a showMessage in the d7zipFile function for both filenames. And then be able to do a showMessage in delphiXE2 on the pFatFile variable, which means the strings went both ways OK?

1
You're evidently able to change the D7 code, so why not do the whole thing in XE?500 - Internal Server Error
Change PChar in the calling code to PAnsiChar and fix the omitted calling convention (stdcall) to resync with the D7 prototypes.menjaraz
I think I'd use WideString here. Make it a var param if the DLL has to return a value. That saves you having to allocate in the caller when you don't know the length.David Heffernan
On the other hand, XE2 comes with an excellent ZIP component so perhaps you can do away with the DLLDavid Heffernan

1 Answers

6
votes

By far the easiest way to do this is to use WideString. This is the Delphi wrapper around the COM BSTR type. Dynamic allocation of the string payload is done using the shared COM allocator. Since the Delphi RTL manages that, it is transparent to you.

In the Delphi 7 code you declare your functions like this:

function d7zipFile(const FatFile, ThinFile: WideString): integer; stdcall;
function d7unzipfile(const ThinFile: WideString; var FatFile: WideString): 
    integer; stdcall;

In your calling code you declare the functions like this:

function d7zipFile(const FatFile, ThinFile: WideString): integer; stdcall; 
    external 'd7b64zip.dll';
function d7unzipfile(const ThinFile: WideString; var FatFile: WideString): 
    integer; stdcall; external 'd7b64zip.dll';

The alternative to this approach is to use PAnsiChar or PWideChar. Note that you cannot use PChar because that alias refers to different types depending on which version of Delphi you use. In Delphi 7 PChar is an alias for PAnsiChar, and in XE2 it is an alias for PWideChar.

The big downside of using PAnsiChar, say, is that the caller needs to allocate the string which is returned from the DLL. But typically the caller does not know how large that string needs to be. There are a variety of solutions to the problem but the neatest approach is always to use a shared allocator. You state that you do not want to rely on borlandmm.dll and so the next most obvious common allocator is the COM allocator. And that's why WideString is attractive.