Thanks for the explanation and example, Arno, but I was 1 step ahead of you
in realising the mistake.

What I did (which appears to have worked as the errors are not being
reported now) is to simply move the "Note" variable into the global scope.

The DLL only gets called by one external process so I think it's a
reasonably safe approach... unless you know different. :-)

Regards, Adam

-----Original Message-----
From: twsocket-boun...@elists.org [mailto:twsocket-boun...@elists.org] On
Behalf Of Arno Garrels
Sent: 16 September 2011 07:17
To: ICS support mailing
Subject: Re: [twsocket] DLL implementation advice (or example)...

Adam Burgoyne wrote:
> I've now changed the
> code to this which should solve the problem if I understood correctly:
> 
> function ReadMessage: PAnsiChar; stdcall; var
>  Note: AnsiString;
> begin
>  EnterCriticalSection(CritSectn);
> 
>  if (NotesList.Count > 0) then
>  begin
>    Note := NotesList.Strings[0];
>    NotesList.Delete(0);
>    Result := PAnsiChar(Note);
>  end
>  else
>    Result := '';
> 
>  LeaveCriticalSection(CritSectn);
> end;


That doesn't work either, the string assigned to the local variable is
destroyed when it goes out of scope, that is when the function is left.
You have to change the function like below and have the caller allocate and
free the memory the string is copied to:

{code untested}
function ReadMessage(pBuf: PAnsiChar; pBufSize: PLongWord): LongWord;
stdcall;
begin   
  try
    EnterCriticalSection(CritSectn);
    try
      if pBufSize = nil then
      begin
        Result := 0;
      end
      else if pBuf = nil then
      begin // Return required size / number of AnsiChars
        pBufSize^ := Length(NotesList[0]);
        Result := 0;
      end
      else if pBufSize^ < Length(NotesList[0]) then
      begin // Return required size / number of AnsiChars
        pBufSize^ := Length(NotesList[0]);
        Result := 0;   
      end
      else begin // Return number of copied AnsiChars 
        Result := Length(NotesList[0]);
        Move(Pointer(NotesList[0])^, pBuf^, Result);
        NotesList.Delete(0);
      end;
    finally
      LeaveCriticalSection(CritSectn);
    end;
  except
    Result := 0;
  end;   
end;
{code}

But..
If that function is called from different threads you cannot use it to get
the size of a string in a first call with a nil pBuf since on the second
call the string might no longer be the same. 
   
--
Arno Garrels

--
To unsubscribe or change your settings for TWSocket mailing list please goto
http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

--
To unsubscribe or change your settings for TWSocket mailing list
please goto http://lists.elists.org/cgi-bin/mailman/listinfo/twsocket
Visit our website at http://www.overbyte.be

Reply via email to