views:

245

answers:

2

I'm sending a log message to the main form using this:

For send the message:

procedure LogMsg(Msg: string; Kind:TMsgType=msgNormal);
var
  p: pChar;
begin    
  case Kind of
    msgError: Msg := '[Error] ' + Msg;
    msgInformation: Msg := '# ' + Msg;
    msgExternal: Msg := 'Plugin: ' + Msg;
  end;//if

  GetMem(p, (Length(Msg) + 1)*SizeOf(Char));
  Move(Msg[1], p^, (Length(Msg)+ 1)*SizeOf(Char));

  PostMessage(Application.MainForm.Handle, WM_LOG_MESSAGE, 0, integer(p));
end;

And display it:

procedure TfrmMain.WMLog(var Message: TMessage);
var
  p: pChar;
  Lista:TStringList;
begin
  try
    p := pChar(Message.LParam);

    if EditLog.Lines.Count>100 then
    begin
      EditLog.Lines.Clear;
    end;//if

    Lista := TStringList.Create;
    try
      Lista.Delimiter := #10;
      Lista.text := p;
      EditLog.Lines.AddStrings(Lista);
    finally
      Lista.Free;
    end;//try

{$ifndef FPC}
    EditLog.GotoLineAndCenter( EditLog.Lines.Count );
{$endif}

    Freemem(p);
  except
    on E: Exception do
      EditLog.Lines.Add(E.Classname + ': ' + E.Message);
  end;//try
end;

This is for log the output from execute some python scripts.

However look like if the message string is too large, the process hang and is necesary kill the python process.

I was not aware that could exist a limit. PostMessage have a limit in the size of the data or could be something else?

This is with Delphi 2010.

EDIT: Sorry, I forget to show the type of msg. Is a String.

A: 

I thought you shouldn't use Move. Are you sure all characters are from the same length ?

UPDATE:

GetMem(p, (Length(Msg) + 1)*SizeOf(Char)); 
Move(Msg[1], p^, (Length(Msg)+ 1)*SizeOf(Char)); 

I never have used pChar's too much, but don't you have to append a #0 character to the Msg string before you do this. Delphi 2010 does not zero out memory when using GetMem.

Edelcom
Although there are better ways to make a copy of a string, there's nothing wrong with the code that uses Move. Characters are obviously the same length because it's all in the same program, and he's copying exactly as many characters as he allocated memory for. (The better way is this: `var p: PString; New(p); p^ := Msg;` Then, in the message handler: `var p: PString; p := PString(Msg.LParam); EditLog.Add(p^); Dispose(p);`)
Rob Kennedy
SO, this is the answer, is not a limit on it. Also your code is more clean!.Please put as a answer so I can mark it. The problem with python is related to http://stackoverflow.com/questions/527197/intercepting-stdout-of-a-subprocess-while-it-is-running
mamcx
A: 

I'm taking the other route than mghie here (whoes answer just magically completely and utterly non-magically disappeared on me :P), looking at your code I can only deduce you ARE sending data from within the same process.

You are simply passing a pointer through PostMessage, so there is no limit on message size. When you debug your code (you are debugging that piece of code, right?), on what line does it break? The assignment of .text?

Try assigning the pchar to a string first, and writing that string to a file. If that works, you have a direction to look into.

If that doesn't work, verify using the debugger the pointer is indeed pointing towards a string, and if that string is zero-terminated. From the code you posted, it looks like it is.

Paul-Jan
@Paul-Jan: There's no magic in this disappearing act - on re-reading the question I came to the conclusion that this `PostMessage()` could indeed only be inside of the same application, so I deleted the answer.
mghie
Yes, is inside the same app. I need to do this because the code is on a multi-thread server (using RemObjects) that send log output to the main thread.
mamcx