Re: Convert C-Builder program to Delphi?

W

W. D.

VBDis said:
"W. D." said:
Temp32 = GetChunk(7, &((uint8*)&PackedStruct)[1]);
I realize that this is casting the PackedStruct as
an array of bytes, and we are trying to collect 7
bytes to put into Temp32 starting at the first
byte. (Temp32 is a uint32).

IMO it's starting at the second byte, since C arrays are always zero-based.
Does anyone have an idea why I would get errors
using this?
Temp32 := GetChunk(7, Addr(uint8(Addr(PackedStruct)[1])));

There's one Addr too much :-(
Try:

type Tuint8Array = array[0..7] of uint8;
Temp32 := GetChunk(7, Addr(Tuint8array(PackedStruct)[1]));

DoDi


Thanks DoDi! I'll try that when I get back to it. Right now
this C++ code that I am working on is getting bizzare. As far
as I can tell, the following code is for compatibilty with DLLs.

I Googled just about everyplace I can think of and still
haven't come up with the proper way to translate these
to Delphi:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if !defined (DLLFUNC)
#define DLLFUNC(ret) extern __declspec(dllexport) ret __stdcall
#endif


DLLFUNC(int) SomeDLL_Open();

DLLFUNC(void) SomeDLL_Close();

DLLFUNC(int) SomeDLL_GetData(BYTE* pDataType, const PBYTE* pTheData,
DWORD* pDataSize);

DLLFUNC(int) SomeDLL_Request(BYTE byRequestType, DWORD dwRequestData);

// The result returned is based upon the last function attempted within
this DLL
DLLFUNC(int) SomeDLL_GetErrorCondition();

typedef int (__stdcall *FUNC_OPEN)();
typedef void (__stdcall *FUNC_CLOSE)();
typedef int (__stdcall *FUNC_GET)(BYTE*,PBYTE*,DWORD*);
typedef void (__stdcall *FUNC_SHOWICON)(BOOL);


#endif
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Can anybody spare a hint?

Mucho gracias if you can help!
 
M

Maarten Wiltink

[...] Right now this C++ code that I am working on is getting
bizzare. As far as I can tell, the following code is for
compatibilty with DLLs.

I Googled just about everyplace I can think of and still
haven't come up with the proper way to translate these
to Delphi:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if !defined (DLLFUNC)
#define DLLFUNC(ret) extern __declspec(dllexport) ret __stdcall
#endif

DLLFUNC(int) SomeDLL_Open();

DLLFUNC(T) more or less wraps type T so that declaring a function
to return it is also usefully exported from a DLL this source is
linked into.

It is a macro and depends on C preprocessor macros being textual;
also on the syntactical closeness of the relevant C keywords.
Delphi does not have them all next to each other and doesn't have
macros anyway.

Marking functions as exported is done in the project file in Delphi,
quite separate from the function declaration itself. The calling
convention is given by a directive added after the declaration but
it marks up the declaration as a whole, not just the type. (That's
true also for C, but macros don't care.)

Look for "exports" and "stdcall" in the help.

Groetjes,
Maarten Wiltink
 
W

W. D.

Maarten said:
[...] Right now this C++ code that I am working on is getting
bizzare. As far as I can tell, the following code is for
compatibilty with DLLs.

I Googled just about everyplace I can think of and still
haven't come up with the proper way to translate these
to Delphi:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if !defined (DLLFUNC)
#define DLLFUNC(ret) extern __declspec(dllexport) ret __stdcall
#endif

DLLFUNC(int) SomeDLL_Open();

DLLFUNC(T) more or less wraps type T so that declaring a function
to return it is also usefully exported from a DLL this source is
linked into.

It is a macro and depends on C preprocessor macros being textual;
also on the syntactical closeness of the relevant C keywords.
Delphi does not have them all next to each other and doesn't have
macros anyway.

Marking functions as exported is done in the project file in Delphi,
quite separate from the function declaration itself. The calling
convention is given by a directive added after the declaration but
it marks up the declaration as a whole, not just the type. (That's
true also for C, but macros don't care.)

Look for "exports" and "stdcall" in the help.

Groetjes,
Maarten Wiltink
Oh boy. This C++ code that I am working on is getting
bizzare. As far as I can tell, this code is for compatibilty with DLLs.

I Googled just about everyplace I can think of and still haven't come up with
the proper way to translate these to Delphi:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#if !defined (DLLFUNC)
#define DLLFUNC(ret) extern __declspec(dllexport) ret __stdcall #endif


DLLFUNC(int) SomeDLL_Open();

DLLFUNC(void) SomeDLL_Close();

DLLFUNC(int) SomeDLL_GetData(BYTE* pDataType, const PBYTE* pTheData, DWORD* pDataSize);

DLLFUNC(int) SomeDLL_Request(BYTE byRequestType, DWORD dwRequestData);

// The result returned is based upon the last function attempted within this DLL
DLLFUNC(int) SomeDLL_GetErrorCondition();

typedef int (__stdcall *FUNC_OPEN)();
typedef void (__stdcall *FUNC_CLOSE)();
typedef int (__stdcall *FUNC_GET)(BYTE*,PBYTE*,DWORD*);
typedef void (__stdcall *FUNC_SHOWICON)(BOOL);


#endif ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Can anybody spare a hint?

This appears to me to be an overly cute approach of defining a
consistent interface onto some exported DLL functions. I guess it might
have some benefit if the calling signature is expected to change, this
way the only place anything needs to be changed is in the #define macro.

The thing to remember about C/C++ preprocessor #defines is that it's
really just a TEXT substitution mechanism. Since Delphi doesn't have
anything quite like this, the usual approach is to expand the #define
into actual Delphi code; sometimes this comes out as a CONST
declaration, sometimes it converts to a function, in this case it
decorates some function declarations elsewhere in your code.

So, what is this actually saying?:
#define DLLFUNC(ret) extern __declspec(dllexport) ret __stdcall

It says whenever the preprocessor encounters the text string "DLLFUNC",
replace it with the defined text. the "(ret)" acts as a parameter,
saying whatever text appears in parentheses after "DLLFUNC" should be
inserted whereever "ret" appears in the macro string.

So lets get down to cases, first a step-by-step substitution so you can
see how that works.
DLLFUNC(int) SomeDLL_Open();

1. We found DLLFUNC so insert its definition at that location in the source:

extern __declspec(dllexport) ret __stdcall

2. Append the original call

extern __declspec(dllexport) ret __stdcall SomeDLL_Open();

3. Now we passed in "int" as the parameter, so replace any instances of
"ret" with "int":

extern __declspec(dllexport) int __stdcall SomeDLL_Open();

So, that's what the code looks like at after the first macro pass. Now,
"__declspec" is a standard C++ macro, read about __declspec here:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vccore/html
/_core_export_from_a_dll_using___declspec.28.dllexport.29.asp

But given what it does, I don't think you need to worry too much about
its exact expansion. My first guess at a Delphi translation:

function SomeDLL_Open(): Integer; stdcall; name 'SomeDLL_Open';

This declaration would go in a "Exports" section of your DLL.

Similarly:
DLLFUNC(void) SomeDLL_Close();

extern __declspec(dllexport) void __stdcall SomeDLL_Close();
DLLFUNC(int) SomeDLL_GetData(BYTE* pDataType, const PBYTE* pTheData,
DWORD* pDataSize);

extern __declspec(dllexport) int __stdcall SomeDLL_GetData(
BYTE* pDataType, const PBYTE* pTheData, DWORD* pDataSize);
DLLFUNC(int) SomeDLL_Request(BYTE byRequestType, DWORD dwRequestData);

extern __declspec(dllexport) int __stdcall SomeDLL_Request(
BYTE byRequestType, DWORD dwRequestData);
DLLFUNC(int) SomeDLL_GetErrorCondition();

extern __declspec(dllexport) int __stdcall SomeDLL_GetErrorCondition()

HTH

Yes, it sure did--Thanks Stephen. (thanks Maarten, and Eugenijus too!)

What I came up with that compiled is:

// Trashed the macro, and manually constructed the statements...

// C++: DLLFUNC(int) SomeDLL_Open();
Function SomeDLL_Open(): Integer; StdCall;
Exports SomeDLL_Open Name 'SomeDLL_Open';

// Apparently, the 'Exports' keyword can be placed anywhere, so
// why not just after the Function is declared?


// C++: DLLFUNC(void) SomeDLL_Close();
Procedure SomeDLL_Close(); StdCall;
Exports SomeDLL_Close Name 'SomeDLL_Close';

// C++: DLLFUNC(int) SomeDLL_GetData(BYTE* pDataType,
// const PBYTE* pTheData, DWORD* pDataSize);
Function SomeDLL_GetData(pDataType: Byte; const pTheData: PBYTE;
pDataSize: LongInt): Integer; StdCall;
Exports SomeDLL_GetData NAME 'SomeDLL_GetData';

// C++: DLLFUNC(int) SomeDLL_Request(BYTE byRequestType, DWORD
dwRequestData);
Function SomeDLL_Request(byRequestType: Byte; dwRequestData: LongInt):
Integer; StdCall;
Exports SomeDLL_Request NAME 'SomeDLL_Request';

Now I have a few more questions: Even though this format
compiles, will I have any problems with the pointers that
I pretty much ignored in these translations? If so, how
should I alter this code?

Also, Type definitions 1, & 2, below seem to make sense,
but #3 has multiple data types as arguments. And #4 has
that extra parameter, 'BOOL'. What should I do in this
case?

// (1) C++: typedef int (__stdcall *FUNC_OPEN)();
Type FUNC_OPEN = Function(): Integer; StdCall;

// (2) C++: typedef void (__stdcall *FUNC_CLOSE)();
Type FUNC_CLOSE = Function(): Integer; StdCall;

// (3) C++: typedef int (__stdcall *FUNC_GET)(BYTE*,PBYTE*,DWORD*);
Type FUNC_GET = Function({ ???? }): Integer; StdCall;

// (4) C++: typedef void (__stdcall *FUNC_SHOWICON)(BOOL);
Type FUNC_SHOWICON = Procedure(); StdCall;


Thanks for all the light you guys are shining my way!
 
M

Maarten Wiltink

[...]
// C++: DLLFUNC(int) SomeDLL_Open();
Function SomeDLL_Open(): Integer; StdCall;
Exports SomeDLL_Open Name 'SomeDLL_Open';

// Apparently, the 'Exports' keyword can be placed anywhere, so
// why not just after the Function is declared?

It can? I didn't know that. It seems to be customary to have
all the exports together in the project file. There are things
to be said for both.


[...]
Now I have a few more questions: Even though this format
compiles, will I have any problems with the pointers that
I pretty much ignored in these translations? If so, how
should I alter this code?

Yes, that's one ugly habit you have. A pointer to something is
something decidedly different from the thing itself. You cannot
treat them as anything close to interchangeable.

If T is a type identifier, ^T is a type for pointers to items
of type T. For many types TX, a corresponding type PX already
exists which is a pointer to TX. The issue is muddied by the
fact the in C, an array is declared as a pointer to the first
element and further elements are accessed through pointer
arithmetic.

Also, Type definitions 1, & 2, below seem to make sense,
but #3 has multiple data types as arguments. And #4 has
that extra parameter, 'BOOL'. What should I do in this
case?

// (1) C++: typedef int (__stdcall *FUNC_OPEN)();
Type FUNC_OPEN = Function(): Integer; StdCall;

// (2) C++: typedef void (__stdcall *FUNC_CLOSE)();
Type FUNC_CLOSE = Function(): Integer; StdCall;

// (3) C++: typedef int (__stdcall *FUNC_GET)(BYTE*,PBYTE*,DWORD*);
Type FUNC_GET = Function({ ???? }): Integer; StdCall;

// (4) C++: typedef void (__stdcall *FUNC_SHOWICON)(BOOL);
Type FUNC_SHOWICON = Procedure(); StdCall;

You know what a procedure prototype looks like in Pascal, right?
In C, you're allowed to leave out the parameter names because they
don't need to match anyway. Pascal makes you include formal names
because otherwise it wouldn't look like Pascal or something.

As for "BOOL", see "LongBool".

Groetjes,
Maarten Wiltink
 
W

W. D.

Maarten said:
[...]
// C++: DLLFUNC(int) SomeDLL_Open();
Function SomeDLL_Open(): Integer; StdCall;
Exports SomeDLL_Open Name 'SomeDLL_Open';

// Apparently, the 'Exports' keyword can be placed anywhere, so
// why not just after the Function is declared?

It can? I didn't know that. It seems to be customary to have
all the exports together in the project file. There are things
to be said for both.

Yep. From the help file:

"An exports clause can appear anywhere and any number of
times in the declaration part of a program or library,
or in the interface or implementation section of a unit.
Programs seldom contain an exports clause."

[...]
Now I have a few more questions: Even though this format
compiles, will I have any problems with the pointers that
I pretty much ignored in these translations? If so, how
should I alter this code?

Yes, that's one ugly habit you have. A pointer to something is
something decidedly different from the thing itself. You cannot
treat them as anything close to interchangeable.

Understood. Delphi is supposed to automatically handle the
pointers in various data types, so I am perplexed when to use
them when C requires manual handling.

If T is a type identifier, ^T is a type for pointers to items
of type T. For many types TX, a corresponding type PX already
exists which is a pointer to TX. The issue is muddied by the
fact the in C, an array is declared as a pointer to the first
element and further elements are accessed through pointer
arithmetic.

Exactly. Can anyone 'point' to a cheat sheet on pointer
arithmetic in Delphi?
You know what a procedure prototype looks like in Pascal, right?
In C, you're allowed to leave out the parameter names because they
don't need to match anyway. Pascal makes you include formal names
because otherwise it wouldn't look like Pascal or something.

Right. That's why I like Pascal--it keeps you out of run-time
trouble.

In these cases, is *ANYTHING* needed inside parentheses, or will
Delphi allow any type of data types?

Also, when there is a parameter at the end, should I just ignore
it as is the case with '(BOOL)'?
As for "BOOL", see "LongBool".

Hmmm. LongBool -- that's a new one for me. I wonder why more
than 1 type of boolean would be needed. I guess just for type
matching. In this conversion, I've just been using 'Boolean'.
According to the Help file a LongBool takes up 4 bytes:

A Boolean variable occupies one byte of memory, a ByteBool
variable also occupies one byte, a WordBool variable
occupies two bytes (one word), and a LongBool variable
occupies four bytes (two words).

It's also interesting that Dr. Bob's HeadConv page shows
'Bool', which doesn't exist in Delphi/Pascal as far as I
know:

http://www.drbob42.com/delphi/headconv.htm
 
M

Maarten Wiltink

W. D. said:
Maarten said:

[...] From the help file:

"An exports clause can appear anywhere and any number of
times in the declaration part of a program or library,
or in the interface or implementation section of a unit.
Programs seldom contain an exports clause."

Okay. I learned something, too.

Understood. Delphi is supposed to automatically handle the
pointers in various data types, so I am perplexed when to use
them when C requires manual handling.

When you're interfacing with other languages, you can't take
things for granted anymore. You have to get them _right_. Delphi
doesn't much encourage that otherwise, that's true.

[...] Can anyone 'point' to a cheat sheet on pointer
arithmetic in Delphi?

There isn't much to it at all. It's exactly the same as in C, really.
Addition to a typed pointer is scaled by the referenced type. Add 1 to
a PChar and the pointer is moved by 1 Char. Add 1 to a PWideChar and
the pointer is moved by 1 WideChar. Add 34 to a ^Widget and the pointer
is moved by 34 Widgets.

Untyped pointers shouldn't be subjected to this. At all. Even if the
compiler doesn't complain. (Looks down) Anyone else for this soapbox?


[...]
In these cases, is *ANYTHING* needed inside parentheses, or will
Delphi allow any type of data types?

If you want parameters, put them where you'd expect. The parameters
(their types, if not their names) are an integral part of a procedural
type. Pascal is strongly typed. Draw your own conclusions (or witness
the compilation errors).

Also, when there is a parameter at the end, should I just ignore
it as is the case with '(BOOL)'?

You should stop ignoring things.

Hmmm. LongBool -- that's a new one for me. I wonder why more
than 1 type of boolean would be needed. ...

Exactly for interfacing with other languages.


[...]
It's also interesting that Dr. Bob's HeadConv page shows
'Bool', which doesn't exist in Delphi/Pascal as far as I
know:

http://www.drbob42.com/delphi/headconv.htm

Bool is declared to be LongBool in the Windows unit.

Groetjes,
Maarten Wiltink
 
W

W. D.

Maarten said:
Yes. But that loses the whole point. Cast a pointer to a number and
addition reverts to addition of integers. No scaling any more.

Groetjes,
Maarten Wiltink

Thanks, Maarten, Jamie, and Dodi!

Now I have a problem translating a C declaration with pointers:

* ((uint32 *)&DataArry[2]) = SomeFunc(SomeVar);

After studying various sources, including:

http://www.sun.com/971124/cover-linden/cchap.html
http://www.sun.com/971124/cover-linden/decoder.gif
http://www-ccs.ucsd.edu/c/syntax.html

I've translated the line as follows:

The actual data of ((int pointer to) the address of DataArray[2])
takes the value of SomeFunc(SomeVar)

Using my knowledge of Pascal operators, I translate
this into:

^(( (^uint32)@DataArray[2] ) := SomeFunc(SomeVar);

Of course, it doesn't compile! Any comments, hints, etc.????

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Also, I've translated this:

uint8 DataArray[8] = {0x44, 0, 0, 0, 0, 0, 0, 0};

into this:

Var
DataArray: array [1..8] of uint8;

DataArray[8] := ($44, $0, $0, $0, $0, $0, $0, $0); // Doesn't
compile!!!
// DataArray[8] := $44; <-- This does compile.

What's going on here????

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Thanks, guys for all your help!!!!!!
 
M

Maarten Wiltink

[...] I have a problem translating a C declaration with pointers:

* ((uint32 *)&DataArry[2]) = SomeFunc(SomeVar);
[...] I've translated the line as follows:

The actual data of ((int pointer to) the address of DataArray[2])
takes the value of SomeFunc(SomeVar)

Using my knowledge of Pascal operators, I translate
this into:

^(( (^uint32)@DataArray[2] ) := SomeFunc(SomeVar);

Of course, it doesn't compile! Any comments, hints, etc.????

When writing Pascal, write Pascal. A typecast is written "(T)X" in
C, "T(X)" in Pascal. A dereferencing operation is written "*P" in
C, "P^" in Pascal.

You can never have too many brackets.

Make it "(PInteger(@(DataArray[2])))^ := SomeFunc();" and it should
compile. But the question does suggest itself if DataArray has to
be declared as a byte array. That code writes a 32-bit integer into
it; should it perhaps be an array of integers, or a record?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Also, I've translated this:

uint8 DataArray[8] = {0x44, 0, 0, 0, 0, 0, 0, 0};

into this:

Var
DataArray: array [1..8] of uint8;

In C, array indices run from 0 to N-1.

DataArray[8] := ($44, $0, $0, $0, $0, $0, $0, $0); // Doesn't
compile!!!
// DataArray[8] := $44; <-- This does compile.

What's going on here????

DataArray[8] is one element in the array. It's what square brackets do.
Anyway, you can't initialise an entire array in one statement like
that. In a constant declaration you can, but nowhere else. There are
tricks but for now, just write out the eight statements.

Groetjes,
Maarten Wiltink
 
J

Jamie

W. D. said:
Maarten said:
Yes. But that loses the whole point. Cast a pointer to a number and
addition reverts to addition of integers. No scaling any more.

Groetjes,
Maarten Wiltink


Thanks, Maarten, Jamie, and Dodi!

Now I have a problem translating a C declaration with pointers:

* ((uint32 *)&DataArry[2]) = SomeFunc(SomeVar);
With out knowing the type DataArray points to i can only
assume its a byte/char field(maybe).

PDword(@DataArray[2])^ := SomeFunc(SomeVar);

(unit32 *) is a type cast to force the value to the right
(being the address returned) to reflect as pointer to an
unsigned integer, in delphi this would be a DWORD but you
could actually use integer (pinteger) in its place most likely.
@ does the &,PDword does the (uint32) and the ^ does the * (....

i am sure if i have something wrong here i will be corrected. :)
P.S.
if you don't have the PDword type you can do this.
Type
PDword = ^word;
etc.
 
J

Jamie

W. D. said:
Maarten said:
Yes. But that loses the whole point. Cast a pointer to a number and
addition reverts to addition of integers. No scaling any more.

Groetjes,
Maarten Wiltink


Thanks, Maarten, Jamie, and Dodi!

Now I have a problem translating a C declaration with pointers:

* ((uint32 *)&DataArry[2]) = SomeFunc(SomeVar);
on that last message i sent, the type should be
Type
PDword = ^Dword; // not word :)
 
W

W. D.

Hi Folks,

Thanks to all those who have been helping me in this
struggle to convert this C-code to Delphi!

Hopefully, someone has seen this type of 'struct' that
looks like a class:

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
struct _DBFieldName
{
char FieldName[40];
};


struct DBFieldNames
{
uint16 NumFieldNames;
_DBFieldName *Names;

DBFieldNames()
{ Names = NULL; }

~DBFieldNames()
{ delete[] Names; Names = NULL; }
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Is there similar 'Record' syntax that would work,
or should I make this a class, or what????

Thank you so kindly for your assistance!
 
N

Nicolai Hansen

struct _DBFieldName
{
char FieldName[40];
};


struct DBFieldNames
{
uint16 NumFieldNames;
_DBFieldName *Names;

DBFieldNames()
{ Names = NULL; }

~DBFieldNames()
{ delete[] Names; Names = NULL; }
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

something like

type
TDBFieldName=String[40];
PDBFieldName=^TDBFieldName;

TDBFieldNames=object
Names: PDBFieldName;
constructor Create;
destructor Destroy;
end;

implementation

constructor TDBFieldNames.Create
begin
Names:=nil;
end;

destructor TDBFieldNames.Destroy;
begin
dispose(Names);
Names:=nil;
end;
 
W

W. D.

Thanks, Nicolai, Jonathan, Lennie, Roger, Stephen, & Walter!

I think I'll try it as a class and see if it works. Otherwise
I'll go back and kludge together a record.


Now I have some lines as follows:

#pragma pack (1)

and

#pragma pack()


According to Rudy:

http://rvelthuis.bei.t-online.de/articles/articles-convert.htm#aligns
If alignment is set to 1, no filling will occur at all,
and the sum of the member sizes is the same as the size
of the struct. This is equivalent to a packed record in
Delphi. Note: filler bytes are also inserted after the
last field of a record, to align the next record, for
instance in an array, as well.

Am I correct in assuming that '#pragma pack()' means
to align at 8 bits, with filler bits as needed?

How would these 2 lines differ in Delphi code?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
SomePackedRecord = Packed Record

// Record elements...

End; // SomePackedRecord = Packed Record
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~


Thanks again for your help!!!!!!!



Nicolai said:
struct _DBFieldName
{
char FieldName[40];
};


struct DBFieldNames
{
uint16 NumFieldNames;
_DBFieldName *Names;

DBFieldNames()
{ Names = NULL; }

~DBFieldNames()
{ delete[] Names; Names = NULL; }
};
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

something like

type
TDBFieldName=String[40];
PDBFieldName=^TDBFieldName;

TDBFieldNames=object
Names: PDBFieldName;
constructor Create;
destructor Destroy;
end;

implementation

constructor TDBFieldNames.Create
begin
Names:=nil;
end;

destructor TDBFieldNames.Destroy;
begin
dispose(Names);
Names:=nil;
end;
 
W

W. D.

Thanks, Jonathan, Roger, Nicolai for your help!

Does anyone know how I can check for the end of
file for a pointer to a FILE?



Type
FilePtr = ^File;

Public
// static void SetFileHandle(FILE *fp) // {my_fp = fp;}
Procedure SetFileHandle(fp: FilePtr);

Private

// The constructors use this file handle to load data from
// C++: static FILE *my_fp;
my_fp: FilePtr;


// C++: if (my_fp)
If (my_fp <> NIL) Then {do stuff} ;


// C++: if (!feof(my_fp))
If (NOT EOF(my_fp)) Then {do stuff} ;

// ^^^ I get an 'Incompatible Types' error here.


Any ideas on how to test for the end of file using
a pointer to a FILE?

Many thanks for any light you can shed!!!!
 
M

Maarten Wiltink

Does anyone know how I can check for the end of
file for a pointer to a FILE?

Dereference it so it becomes a file again, and call Eof() on that.
But why hide it behind a pointer in the first place?

Groetjes,
Maarten Wiltink
 
W

W. D.

Thanks Eddie, Mike, and Maarten!!!
Would it be?
if (NOT EOF(my_fp^)) then {do stuff} ;

The ^ at the end should dereference the pointer.

I guess that should have been obvious. It compiles
fine now.

Maarten said:
But why hide it behind a pointer in the first place?

Good question. I am trying to duplicate the C++ code,
and that is how it is written. Once I get all the code
converted and compiled, I'll then need to debug everything.
Who knows how much I'll have to change everything around.

Does anyone know the equivalent of C++'s 'Delete[]' in
Delphi?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// C++: char *RawData;
RawData: PChar;

// C++: FieldTyypes *The_Fields;
The_Fields: FieldTyypesPtr;


// C++: SOMEDB::~SOMEDB()
Destructor SOMEDB.Destroy;

// C++: {
Begin

delete[] RawData;
delete[] The_Fields;

// C++: }
End; // Destructor SOMEDB.Destroy;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
M

Maarten Wiltink

W. D. said:
Maarten Wiltink wrote:

Good question. I am trying to duplicate the C++ code,
and that is how it is written.

C does not have var parameters. So when you need one, you
pass a pointer to your variable. You'll notice that all
the traditional-style I/O functions in Pascal (WriteLn for
example) pass the file variable by reference.


[...]
Does anyone know the equivalent of C++'s 'Delete[]' in
Delphi?

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// C++: char *RawData;
RawData: PChar;

// C++: FieldTyypes *The_Fields;
The_Fields: FieldTyypesPtr;


// C++: SOMEDB::~SOMEDB()
Destructor SOMEDB.Destroy;

// C++: {
Begin

delete[] RawData;
delete[] The_Fields;

// C++: }
End; // Destructor SOMEDB.Destroy;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

It looks like an array deallocator. If you translated these things into
dynamic arrays, letting the references go out of scope should be enough.
If you want to be explicit about it, SetLength() them to zero elements.
(Personally, I don't like setting things that aren't pointers to nil,
and arrays aren't pointers in the language even if they are in an
implementation.)

A dynamic array of Char is of course a (long) string and may be handled
in the same way, although I would intuitively clear a dynamic array in
a destructor but never a string. The name RawData on the other hand,
suggest that it should really have been an opaque buffer of _bytes_,
not characters.

Groetjes,
Maarten Wiltink
 
R

Rudy Velthuis

Maarten said:
C does not have var parameters. So when you need one, you
pass a pointer to your variable.

Actually, I think current C has. But headers are of course compatible
with older C versions as well.
 
M

Maarten Wiltink

Rudy Velthuis said:
Maarten Wiltink wrote:

Actually, I think current C has. But headers are of course
compatible with older C versions as well.

Ah yes, that rings a bell. Something about the latest C (C++?)
standard thinking two kinds of pointers weren't enough and
adding a third.

Groetjes,
Maarten Wiltink
 
R

Rudy Velthuis

Maarten said:
Ah yes, that rings a bell. Something about the latest C (C++?)
standard thinking two kinds of pointers weren't enough and
adding a third.

Two kinds? Oh, you mean arrays and plain pointers? Now they have
references as well, IIRC. C++ most certainly has them.

--
Rudy Velthuis http://rvelthuis.bei.t-online.de

"The only thing necessary for the triumph of evil is for good men to do
nothing."
-- Edmund Burke (1729-1797)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,230
Members
46,816
Latest member
SapanaCarpetStudio

Latest Threads

Top