tags:

views:

178

answers:

2

I created a function similar below in delphi code. but it wont work. What is the proper way to convert this?

char* ReadSpeechFile(char* pFileName, int *nFileSize)
{
    char *szBuf, *pLinearPCM;   
    int nSize;
    FILE* fp;

    //read wave data
    fp = fopen(pFileName, "rb");
    if(fp == NULL)
        return NULL;
    fseek(fp, 0, SEEK_END);
    nSize = ftell(fp);

    //linear
    szBuf = (char *)calloc(nSize, sizeof(char));
    fseek(fp, 0, SEEK_SET);
    fread(szBuf, sizeof(char), nSize, fp);
    fclose(fp);

    *nFileSize = nSize;

    return szBuf;
}
+4  A: 

I will translate this to the following Delphi code (not tested):

function ReadSpeechFile(pFileName: PAnsiChar, var nFileSize: Integer): PAnsiChar;
var
 szBuf: PAnsiChar;
 nSize: Integer;
 fp: TFileStream;
begin
  fp := TFilestream.Create(pFileName, fmOpenRead);
  try
    nSize := fp.Size;
    GetMem(szBuf, nSize);
    fp.Read(szBuf^, nSize);
  finally
    fp.Free;
  end;
  nFileSize := nSize;
  Result := szBuf;
end;
da-soft
A proper conversion to Delphi code would return a string, not a `PAnsiChar`. The result can still be type-cast to `PAnsiChar`, but there's no risk of leaking memory.
mghie
@mghie: I agree but what's "proper" probably depends on context. For example, you might need to pass the function pointer to another API and therefore keep the original signature.
TOndrej
@mghie: Well ... There may be many options to convert this to Delphi. Like a use TFileStream or TEXT, use AnsiString or PAnsiChar, etc. I just gave a most closest (from my POV) translation.
da-soft
hi to all! i alredy tested the code above it has no error,but returns empty except the nFileSize. any other ideas? do i need to post the file to be open? the file type is *.PCM
XBasic3000
What means "empty" and how you have verified that ? Actually, you are reading a binary file into PAnsiChar buffer. So, if a first byte is #0, then Ctrl+F4 (or similar tools) will show to you an empty string.
da-soft
@Dmitry Arefiev, please help.. ive done it like szBufRef := ReadSpeechFile(szRefFN, nBufRefLen);my debugger say's, szBufRef |''
XBasic3000
That is ok - just use szBufRef as you need. Or replace the buffer type from PAnsiChar to Pointer or PByte, as more appropriate to your case.
da-soft
@da-soft: There may be many options, but wouldn't you agree that the most idiomatic conversion (and the one with the least possibility to screw up) is preferable?
mghie
I agree with TOndrej :) Actually I prefer to give most closest translation without knowledge of a context. Just imagine, if somebody will ask you to translate only "char *p;", how you will suggest ?
da-soft
I never really like functions that return results both as the function result and in one or more of its parameters.
ldsandon
+2  A: 

How about this

function ReadSpeechFile(const AFileName: string): TMemoryStream;
begin
  Result := TMemoryStream.Create;
  try
    Result.LoadFromFile(AFileName);
  except
    FreeAndNil(Result);
    raise;
  end;
end;

It's more "delphish", does the same, skips string encoding problems. You can use it like this:

Speech := ReadSpeechFile('C:\somefile.dat');
MySize := Speech.Size;  
...
dmajkic
but how to assign the buffer to the PAnsiChar?
XBasic3000
Isn't it better to use finally, instead of except and re-raise? Does the same job and looks prettier to me.
Kcats
@XBasic3000: It is common to use char* in C as an arbitrary buffer. The thing I wrote is more from Delphi point of view. Also SetString(S, Buffer, Len) will copy buffer to S, And then you can pass PAnsiChar(S) to functions.
dmajkic
@Kcats: If there is an exception, MemoryStream object should be freed before exception is raised to avoid memory leak. If there is no exception, object is returned to caller and it should be freed after use.
dmajkic
i see got it. thanx for the comment
XBasic3000
@dmajkic: I feel dumb for not noticing the object is returned
Kcats