Calling Delphi 6 DLL from Delphi 2010

We have a Delphi 6 dll that has a PChar passed to it.  The dll function then does a search and returns a PCHar.  This works good using Delphi 6 to call and recieve the dll 

result.  We have upgraded our calling program to Delphi 2010 and most of the time, the value is passed back just fine.  However, we do have times when we get an access 

violation, when calling the dll.  The dll does process the request.   Below is the code.  Has anyone had a similar issue using an older version Delphi Dll with Delphi 2010?  I am sure that Unicode has something to do with it, but not sure how to fix this.  

TIA


 This is the function in the dll.

function ContactSearch(aCriteria: PChar):PChar; stdcall;
var
 lCriteria: String;
begin
lCriteria := aCriteria;
lCriteria := Verify(lCriteria, 'Contact');
Result := PChar(lCriteria);
end;

 

Delphi 2010 calling code

   var
    lRequest: AnsiString;
    dllResult: String;

         dllHandle := LoadLibrary('Search.dll') ;
          if dllHandle <> 0 then
          begin
            @FuncContactSearch := GetProcAddress(dllHandle, 'ContactSearch') ;
            if Assigned (FuncContactSearch) then
             begin
               dllResult := PAnsiChar(FuncContactSearch(PChar(lRequest)));  <---  This populates dllResult with the string that is returned.  This is also where I get a memory error   

             sometimes and it does not populate dllResult  

            // dllResult := FuncContactySearch(PChar(lRequest)) ; //call the function <-- This call would not populate dllResult wi
0
Jan
2/27/2013 11:38:44 PM
embarcadero.delphi.general 4258 articles. 0 followers. Follow

4 Replies
1420 Views

Similar Articles

[PageSpeed] 41

Jan wrote:

> We have a Delphi 6 dll that has a PChar passed to it.

PChar in D6 was an alias for PAnsiChar, but is now an alias for PWideChar 
in D2009+.  You need to adjust your D2010 code accordingly to use PAnsiChar 
directly instead of PChar generically.

> function ContactSearch(aCriteria: PChar):PChar; stdcall;
> var
>   lCriteria: String;
> begin
>   lCriteria := aCriteria;
>   lCriteria := Verify(lCriteria, 'Contact');
>   Result := PChar(lCriteria);
> end;

This kind of code is very dangerous, even in D6.  You are returning a PAnsiChar 
to an AnsiString that gets freed when the function exits, thus returning 
a pointer to invalid memory.  The fact that it works at all simply means 
that the caller is using the pointer before the Memory Manager has a chance 
to overwrite the freed data with something else.  Don't rely on that behavior.

If you need the returned data to persist after the function exits, you must 
either:

1) save the result of the search in a global variable inside of the DLL so 
it remains in memory, then you can return a pointer to it:

{code:delphi}
var
  // if the function gets called by multiple threads, you will have to declare
  // this variable as 'threadvar' so each thread gets its own copy of the 
variable...
  CriteriaResult: String;

function ContactSearch(aCriteria: PChar):PChar; stdcall;
var
  lCriteria: String;
begin
  lCriteria := aCriteria;
  CriteriaResult := Verify(lCriteria, 'Contact');
  Result := PChar(CriteriaResult);
end;
{code}

2) dynamically allocate a memory block to return, and then require the caller 
to pass it back to the DLL when finished using it so it can be freed correctly:

{code:delphi}
function ContactSearch(aCriteria: PChar):PChar; stdcall;
var
  lCriteria: String;
begin
  lCriteria := aCriteria;
  lCriteria := Verify(lCriteria, 'Contact');
  Result := StrNew(PChar(lCriteria));
end;

procedure FreeContactSearchResult(aResult: PChar); stdcall;
begin
  StrDispose(aResult);
end;
{code}

{code:delphi}
var
  dllResult: PAnsiChar;

dllResult := ContactSearch(...);
if dllResult <> nil then
begin
  // use dllResult as needed...
  FreeContactSearchResult(dllResult);
end;
{code}

3) have the caller pass in a block of memory for the DLL to fill in, that 
way the caller decides how to manage the memory:

{code}
function ContactSearch(aCriteria: PChar; aResultBuffer: PChar; aBufferSize: 
Cardinal): Cardinal; stdcall;
var
  lCriteria: String;
  lResultLen: Cardinal
begin
  lCriteria := aCriteria;
  lCriteria := Verify(lCriteria, 'Contact');
  lResultLen := Min(aBufferSize, Length(lCriteria));
  StrPLCopy(aResultBuffer, lCriteria, aBufferSize);
  Result := lResultLen;
end;
{code}

{code:delphi}
var
  dllResult: array[0..255] of AnsiChar;
  dllResultLen: Cardinal;
begin
  dllResultLen := ContactSearch(..., dllResult, 256);
  // use dllResult up to dllResultLen AnsiChars as needed...
{code}

{code:delphi}
var
  dllResult: AnsiString;
  dllResultLen: Cardinal;
begin
  SetLength(dllResult, 256);
  SetLength(dllResult, ContactSearch(..., PAnsiChar(dllResult), 256));
  // use dllResult as needed...
{code}

> I am sure that Unicode has something to do with it, but not sure how to 
fix this. 

It is OK to assign a PAnsiChar to a UnicodeString. The RTL will perform an 
Ansi->Unicode conversion for you.  However, you are casting an AnsiString 
to a PWideChar, which should not even compile let alone work at runtime. 
 Not taking the memory management issue into account, your D2010 code would 
need to look more like this:

{code:delphi}
var
  lRequest: AnsiString;
  dllResult: PAnsiChar;
  FuncContactSearch: function(aCriteria: PAnsiChar): PAnsiChar; stdcall;
begin
  dllHandle := LoadLibrary('Search.dll') ;
  if dllHandle <> 0 then
  begin
    @FuncContactSearch := GetProcAddress(dllHandle, 'ContactSearch') ;
    if Assigned (FuncContactSearch) then
    begin
      dllResult := FuncContactSearch(PAnsiChar(lRequest));
      // use dllResult as needed...
    end;
  end;
end;
{code}

But you do need to take the memory management issue into account, so you 
have to fix your DLL first and then adjust the D2010 code if needed.

--
Remy Lebeau (TeamB)
0
Remy
2/28/2013 12:30:22 AM
Remy:

Would your suggestion require the use of the Borland Memory Manager.  That is one thing the client wants to stay away from?  The Delphi exe is on a network server and we were going to put the dll in the same folder, with the exe.  When multiple clients launch the exe, do we have to use threads, to make sure the client that called the dll frees their copy?  Since I posted this we did change the PChars to PAnsiChar, in the calling program and dll, it did work better.  We still have a few searches that give 
memory errors.  I will give the code below a try and thank you for the samples and advice.

> {quote:title=Remy Lebeau (TeamB) wrote:}{quote}
> Jan wrote:
> 
> > We have a Delphi 6 dll that has a PChar passed to it.
> 
> PChar in D6 was an alias for PAnsiChar, but is now an alias for PWideChar 
> in D2009+.  You need to adjust your D2010 code accordingly to use PAnsiChar 
> directly instead of PChar generically.
> 
> > function ContactSearch(aCriteria: PChar):PChar; stdcall;
> > var
> >   lCriteria: String;
> > begin
> >   lCriteria := aCriteria;
> >   lCriteria := Verify(lCriteria, 'Contact');
> >   Result := PChar(lCriteria);
> > end;
> 
> This kind of code is very dangerous, even in D6.  You are returning a PAnsiChar 
> to an AnsiString that gets freed when the function exits, thus returning 
> a pointer to invalid memory.  The fact that it works at all simply means 
> that the caller is using the pointer before the Memory Manager has a chance 
> to overwrite the freed data with something else.  Don't rely on that behavior.
> 
> If you need the returned data to persist after the function exits, you must 
> either:
> 
> 1) save the result of the search in a global variable inside of the DLL so 
> it remains in memory, then you can return a pointer to it:
> 
> {code:delphi}
> var
>   // if the function gets called by multiple threads, you will have to declare
>   // this variable as 'threadvar' so each thread gets its own copy of the 
> variable...
>   CriteriaResult: String;
> 
> function ContactSearch(aCriteria: PChar):PChar; stdcall;
> var
>   lCriteria: String;
> begin
>   lCriteria := aCriteria;
>   CriteriaResult := Verify(lCriteria, 'Contact');
>   Result := PChar(CriteriaResult);
> end;
> {code}
> 
> 2) dynamically allocate a memory block to return, and then require the caller 
> to pass it back to the DLL when finished using it so it can be freed correctly:
> 
> {code:delphi}
> function ContactSearch(aCriteria: PChar):PChar; stdcall;
> var
>   lCriteria: String;
> begin
>   lCriteria := aCriteria;
>   lCriteria := Verify(lCriteria, 'Contact');
>   Result := StrNew(PChar(lCriteria));
> end;
> 
> procedure FreeContactSearchResult(aResult: PChar); stdcall;
> begin
>   StrDispose(aResult);
> end;
> {code}
> 
> {code:delphi}
> var
>   dllResult: PAnsiChar;
> 
> dllResult := ContactSearch(...);
> if dllResult <> nil then
> begin
>   // use dllResult as needed...
>   FreeContactSearchResult(dllResult);
> end;
> {code}
> 
> 3) have the caller pass in a block of memory for the DLL to fill in, that 
> way the caller decides how to manage the memory:
> 
> {code}
> function ContactSearch(aCriteria: PChar; aResultBuffer: PChar; aBufferSize: 
> Cardinal): Cardinal; stdcall;
> var
>   lCriteria: String;
>   lResultLen: Cardinal
> begin
>   lCriteria := aCriteria;
>   lCriteria := Verify(lCriteria, 'Contact');
>   lResultLen := Min(aBufferSize, Length(lCriteria));
>   StrPLCopy(aResultBuffer, lCriteria, aBufferSize);
>   Result := lResultLen;
> end;
> {code}
> 
> {code:delphi}
> var
>   dllResult: array[0..255] of AnsiChar;
>   dllResultLen: Cardinal;
> begin
>   dllResultLen := ContactSearch(..., dllResult, 256);
>   // use dllResult up to dllResultLen AnsiChars as needed...
> {code}
> 
> {code:delphi}
> var
>   dllResult: AnsiString;
>   dllResultLen: Cardinal;
> begin
>   SetLength(dllResult, 256);
>   SetLength(dllResult, ContactSearch(..., PAnsiChar(dllResult), 256));
>   // use dllResult as needed...
> {code}
> 
> > I am sure that Unicode has something to do with it, but not sure how to 
> fix this. 
> 
> It is OK to assign a PAnsiChar to a UnicodeString. The RTL will perform an 
> Ansi->Unicode conversion for you.  However, you are casting an AnsiString 
> to a PWideChar, which should not even compile let alone work at runtime. 
>  Not taking the memory management issue into account, your D2010 code would 
> need to look more like this:
> 
> {code:delphi}
> var
>   lRequest: AnsiString;
>   dllResult: PAnsiChar;
>   FuncContactSearch: function(aCriteria: PAnsiChar): PAnsiChar; stdcall;
> begin
>   dllHandle := LoadLibrary('Search.dll') ;
>   if dllHandle <> 0 then
>   begin
>     @FuncContactSearch := GetProcAddress(dllHandle, 'ContactSearch') ;
>     if Assigned (FuncContactSearch) then
>     begin
>       dllResult := FuncContactSearch(PAnsiChar(lRequest));
>       // use dllResult as needed...
>     end;
>   end;
> end;
> {code}
> 
> But you do need to take the memory management issue into account, so you 
> have to fix your DLL first and then adjust the D2010 code if needed.
> 
> --
> Remy Lebeau (TeamB)
0
Jan
2/28/2013 1:34:58 AM
Hello Jan,

> Remy:
> 
> Would your suggestion require the use of the Borland Memory Manager.
> That is one thing the client wants to stay away from?

D6 uses the Borland MM by default.  D2010 uses FastMM instead.  You can download 
the full version of FastMM from http://fastmm.sourceforge.net if you want 
to use it in your D6 code.

In any case, any memory allocated by the DLL has to be freed by the DLL, 
and any memory allocated by the app has to be freed by the app.  This ensures 
the same memory manager, whatever it happens to be, is used to allocate a 
free a given block of memory.

> The Delphi exe is on a network server and we were going to put the dll 
in the same
> folder, with the exe.

Do you have to use the DLL version of the Memory Manager at all?  In most 
situations, it is desirable to static-link the MM directly into apps/DLLs 
instead.  The only time where you have to use a external MM is if you are 
using Runtime Packages, so they all share the same MM.

--
Remy Lebeau (TeamB)
0
Remy
2/28/2013 3:21:50 AM
On Wed, 27 Feb 2013 17:34:58 -0800, Jan B <> wrote:

>Remy:
>
>Would your suggestion require the use of the Borland Memory Manager.  That is one thing the client wants to stay away from?  The Delphi exe is on a network server and we were going to put the dll in the same folder, with the exe.  When multiple clients launch the exe, do we have to use threads, to make sure the client that called the dll frees their copy?  Since I posted this we did change the PChars to PAnsiChar, in the calling program and dll, it did work better.  We still have a few searches that give
 
>memory errors.  I will give the code below a try and thank you for the samples and advice.

What you are doing is certain to on occasion fail.  The only question
is the frequency of such failures.

Furthermore, bugs like this are extremely hard to find while
debugging.
0
Loren
2/28/2013 5:04:15 AM
Reply:

Similar Artilces:

from delphi 6 to delphi 2010
Hi. It is possible, with component RX, dxforumlibrary, InfoPower3000Pro, StringAlignGrid. Accepts communication BDE. Thank by comments. excequiel arostica wrote: >Hi. > It is possible, with component RX, dxforumlibrary, >InfoPower3000Pro, StringAlignGrid. Accepts communication BDE. > >Thank by comments. Rx is dead and sources are taken over by jcl/jvcl. I dont know about the rest of the components and i have no experiences with bde over the last 9 years. excequiel arostica wrote: > Hi. > It is possible, with component RX, dxforumlibrary,...

Trying to call a .DLL from Delphi XE (used to work with Delphi 6 :-) )
Hi everyone, I have a problem where perhaps some one could help point me in the right direction. In Delphi 6 I used a stand alone package to train a neural netowrk,. The trained neural network was stored as a .DEF file. The standalone software provided a .DLL and Delphi code to call the network and get the prediced values from your sw. (The .DLL was created in 2002 and apparently is 32 bit.) I have'nt used it for years but am now coming back to it.... I now use Delphi XE on Windows 7 (32 bit) The old .exe's I had compiled from that time work fine. However in Delphi XE ...

Delphi 6 and Delphi 2010 Install same machine
I'm currently still on Delphi 6 for some legacy software, but I'm looking at installing Delphi 2010 on my Windows XP machine. Are there any known issues with installing D2010 on an XP machine that already has Delphi 6 installed? (I'm not talking about updating the projects code/controls/etc, just running the IDE's). > I'm currently still on Delphi 6 for some legacy software, but I'm > looking at installing Delphi 2010 on my Windows XP machine. > > Are there any known issues with installing D2010 on an XP machine that > already has Delphi 6 i...

Delphi 6 to Delphi 2010 upgrade and ADO
We have an application written in Delphi 6 Professional that uses ADO to access databases servers that may be on other PCs in our network. We want to move to Delphi 2010 but can't decide if we need Professional or Enterprise. 2010 Pro has dbGO - will this give us the same functionality as the ADO components we use in Delphi 6 Pro? Thanks, Keith > 2010 Pro has dbGO - will this give us the same functionality as the > ADO components we use in Delphi 6 Pro? Yes. > {quote:title=Joachim Uersfeld wrote:}{quote} > > 2010 Pro has dbGO - will this give us the same func...

Delphi 6 to Delphi 2010 character codes conversion
I an converting a unit from Delphi 6 to Delphi 2010. Everything works except for a couple of character codes, the decimal values are(224 and 227). As far as I can tell when data is loaded from the socket into a buffer, the codes are ok. When they are written to another buffer these 2 codes use the upper case version of the characters(192 and 224). I don' t see it on any other of the codes. I set the code page in the compiler options to 1252, but that did not work. Any other options I can set in Delp hi 2010 to correct this? TIA Jan B wrote: > I an converting a unit from D...

Change icon after migrating from Delphi 6 to Delphi 2010
I have an old project I am moving to Delphi 2010. I have attempted to change the icon for this project by setting the Application icon in the Project Options. After building the project, the exe file shows the new icon. However, when I create a shortcut to my application, the icon is the old Delphi lightning bolt icon. I have tried to get rid of the old icon by completely deleting the RES file and letting Delphi create a new RES file but that didn't change anything. I know I am missing something but I can't seem to find it. Help! RG Robert Gutierrez wrote: > I have a...

Upgrad to Delphi 2010 Enterprise from Delphi 6 Enterprise
Hi, Is it possible to use the upgrade offer when upgrading to "Delphi 2010 Enterprise" from "Delphi 6 Enterprise" ? I can find a lot of different examples on upgrades.... but not this one ;-( Why is the price in the Nordic region higher than if I was buying in US? (40% off....) I've tried to registre my "Delphi 6" in order to reveive the Promo offer key, but I can't registre. Why is this ? Best regards Nils Unfortunately Embarcadero has changed the upgrading rules since February 1st. You can see it at http://www.embarcadero.com/upgrade...

Is dll developed in Delphi 6 works on Delphi 2?
I have a one dll, whose work is to creates a form with some normal vcl controls, print selected tables and email some reports. It was developed in Delphi 6. Can any other application which was developed in Delphi 2 use that dll.? If not, please let me know in which areas i need change. The dll work is only to print and email. With regards, Srikanth Varma Srikanth varma wrote: > I have a one dll, whose work is to creates a form with some normal > vcl controls, print selected tables and email some reports. It was > developed in Delphi 6. Can any other application which was d...

Delphi XE / Delphi 2010
Hello! I noticed that Embarcadero® Delphi® 2010 Version is not on the list of products on Embarcadero page. Or is it still possible to buy it? Will RAD Studio XE compile programs written in Delphi 2010 without problems.? Thanks. Am 13.09.2010 09:04, schrieb Petra Nemec: > Will RAD Studio XE compile programs written in Delphi 2010 without problems.? As always you will probably have to recreate the projects as the import is still a bit -- special. Christian Hello! Does anybody know if it is still possible to get a Delphi2010 trial version (if yes where)? ...

Delphi 5 to Delphi 6 and up
Dear List, Trying to add 7Zip compression support to my delphi application. I am using the ported 7Zip sdk (see their website, they have a link). I am stumped on how to rewrite a single function: function ReverseDecode(var Models: array of SmallInt; ....): ..... where the input is mostly a fixed size array of SmallInt. This code perfectly compiles and functions in Delphi 6 and up, but in Delphi 5 I get the error: There is no overloaded version of 'ReverseDecode' that can be called with these arguments And obviously, the input (fixed) isn't the same as the param de...

dll fails when compiled with delphi 2010, but works with delphi 7
I may be doing good if someone can just point me to the right forum I have not created a dll for some time and have not written one with 2010 before. The dll I am creating will be called as a cfx function by either a ColdFusion or BlueDragon webserver. I have written cfx DLLs in the past. The function declaration is below, it is the standard declaration from ColdFusion or Bluegradon documention on creating a CFX. procedure ProcessTagRequest(Request: TCFXRequest); export; cdecl; Since this was the first time using 2010 I wrote a very basic function to build off that was not much mor...

dynamical DLL loading in delphi 7 & delphi 2010
Hello, i am loading a DLL dynamical in Delphi 7 and Delphi 2010: [delphi] var hDLL: THandle; pCode: Pointer; type TProcMainEntry = function: TForm; begin hDll := 0; if FileExists(Pfad + vpeDllName) then hDLL := LoadLibrary(PChar(Pfad + vpeDllName)) else SetLastError(2); if hDLL = 0 then RaiseLastOSError; pCode := GetProcAddress(hDLL, PChar(vpeFunction)); if pCode = nil then RaiseLastOSError; Result := TProcMainEntry(pcode)(); [/delphi] in delphi 7 there's a variable filled with data of the main application which used in the...

Price of upgrade from Delphi 2010 Professional to Delphi 2010 Enterprise?
It's weird, but I could not find the answer on so simple question not in Embarcadero Shop, neither by the forum search. For example, the shop info about Enterprise upgrade says: The Upgrade product is available to registered owners of 2006-2009 versions, blah-blah... So, if I'm Delphi 2010 Professional user, I even not eligible for upgrade? I have to buy a new version of Enterprise??? But if I'm Delphi 2006 Professional user, I can upgrade. Please clarify this nonsense for me. Exact question is in the subject. Thanks! Hi Dmitri, > It's weird, but I could not...

Delphi and Delphi for .Net
It seems that Delphi for .Net is slower than Delphi Win32 native applicaiton. I would like to know is it true all .Net application is slower than Win32 native applicaiton or it is Delphi for .Net only. Your information is great appreciated, Inung On 2011-06-21 18:20:17 +0100, Inung Huang said: > It seems that Delphi for .Net is slower than Delphi Win32 native applicaiton. > I would like to know is it true all .Net application is slower than > Win32 native applicaiton or it is Delphi for .Net only. If you are only running the code in the application once then, yes, yo...

Web resources about - Calling Delphi 6 DLL from Delphi 2010 - embarcadero.delphi.general

London Calling - Wikipedia, the free encyclopedia
London Calling is the third studio album by the English punk rock band The Clash . It was released in the United Kingdom on 14 December 1979 ...

List of country calling codes - Wikipedia, the free encyclopedia
This is a list of country calling codes defined by ITU-T recommendations E.123 and E.164 , also called IDD ( International Direct Dialling ) ...

Free VoIP Calling Added To Facebook Messenger For IOS In The U.K.
Voice-over-Internet-protocol calling has made its way across the pond for Facebook Messenger users, as the social network updated its iOS version ...

Facebook Video Calling - Facebook
Bring your conversations to life on Facebook. With face-to-face video calling, now you can watch your friends smile, wink and LOL. To get started, ...

Facebook roundup: video ads, voice calling, logos and more
... than three per day at launch. It is unclear whether the ads will autoplay in the feed or not. More Messenger for Android users get free calling ...

Berlin Calling (@neuraum) on Twitter
Sign in Sign up To bring you Twitter, we and our partners use cookies on our and other websites. Cookies help personalize Twitter content, tailor ...

Calling all foodies: Here comes @TwitterFood
There are many thousands of food-related Tweets people send on Twitter each day – Tweets about meals, ingredients, favorites, recipes and dining ...

YUBISASHI NIPPON CALLING ENGLISH for iPhone, iPod touch, and iPad on the iTunes App Store
Get YUBISASHI NIPPON CALLING ENGLISH on the App Store. See screenshots and ratings, and read customer reviews.

Calling woman II - Flickr - Photo Sharing!
Explore Marcel Oosterwijk's photos on Flickr. Marcel Oosterwijk has uploaded 2195 photos to Flickr.

They're back. All-Australian Koels calling in ACT suburbia
Too many Gang-gang cockatoos, our dear territory's faunal emblem,&nbsp;are not enough.

Resources last updated: 11/23/2015 2:09:41 AM