1
votes

I'm converting from C/C++ header to Delphi. I've carefully read the great Rudy's Delphi Corner article about this kind of conversion. Anyway, I'm facing something I'm hard to understand.

There's an opaque pointer, then a function prototype that has that pointer as parameter, followed by the struct declaration og the function type.

Maybe the code will make things clearer.

source .h code:

struct my_ManagedPtr_t_;
typedef struct my_ManagedPtr_t_ my_ManagedPtr_t;

typedef int (*my_ManagedPtr_ManagerFunction_t)(
                                            my_ManagedPtr_t *managedPtr,
                                            const my_ManagedPtr_t *srcPtr,
                                            int operation);

typedef union {
    int   intValue;
    void *ptr;
} my_ManagedPtr_t_data_;

struct my_ManagedPtr_t_ {
    void *pointer;
    my_ManagedPtr_t_data_ userData[4];
    my_ManagedPtr_ManagerFunction_t  manager;
};

typedef struct my_CorrelationId_t_ {
    unsigned int  size:8;       // fill in the size of this struct
    unsigned int  valueType:4;  // type of value held by this correlation id
    unsigned int  classId:16;   // user defined classification id
    unsigned int  reserved:4;   // for internal use must be 0

    union {
        my_UInt64_t      intValue;
        my_ManagedPtr_t  ptrValue;
    } value;
} my_CorrelationId_t;

... i'm lost. :-( I can't figure out where to start. The structure? The function?

Thank you.

2
What aspect are you struggling with? The bitfields? - David Heffernan
The previous part. - Zak Phoenix McKracken
That's rather unclear. There is lots of code prior to the bitfields. I can't see your Delphi code. I hope you aren't hoping somebody will translate this for you. - David Heffernan
Is the circular reference the problem? The struct contains the function pointer, but the function parameters include the struct? - David Heffernan
For unions and bitfields, see my article about such translations. - Rudy Velthuis

2 Answers

2
votes

As you clarified in the comments, the immediate area of confusion for you is the circular reference. The function pointer parameters refer to the struct, but the struct contains the function pointer. In the C code this is dealt with by the opaque struct type declaration which is simply a forward declaration. A forward declaration simply promises that the type will be fully declared at some later point.

In Delphi you can deal with this in a directly analogous manner. You need to use a forward type declaration. I don't want to translate all the types in your question because that would require dealing with unions and bitfields which I deem to be separate topics. Instead I will present a simple Delphi example that shows how to deal with such circular type declarations. You can take the concept and apply it to your specific types.

type
  PMyRecord = ^TMyRecord; // forward declaration
  TMyFunc = function(rec: PMyRecord): Integer; cdecl;
  TMyRecord = record
    Func: TMyFunc;
  end;
1
votes

It is a little hard to find out where to start, but @DavidHeffernan's explanation of forward declaring a pointer type should give you a start.

I would translate this to following (untested) code:

type
  _my_ManagedPtr_p = ^my_ManagedPtr_t;

  my_ManagedPtr_ManagerFunction_t = function(
    managedPtr: my_ManagedPtr_p;
    scrPtr: my_ManagedPtr_p; 
    operation: Integer): Integer cdecl;

  my_ManagedPtr_t_data = record
    case Boolean of
      False: (intValue: Integer);
      True:  (ptr: Pointer);
  end;

  my_ManagedPtr_t = record
    ptr: Pointer;
    userData: array[0..3] of my_ManagedPr_t_data;
    manager: my_ManagedPtr_ManagerFunction_t;
  end;

  my_CorrelationId_t = record
    typeData: UInt32; // size, valueType, classId and reserved combined in one integer.
    case Byte of
       0: (intValue: my_UInt64_t);
       1: (ptrValue: my_ManagedPtr_t;
  end;

I am not going to do the bitfields, but please read the Bitfields section of my article Pitfalls of converting again (I see you mentioned it already) to find a few solutions. If you want to make it really nice, use the methods and indexed access, otherwise just use shifts and masks to access the bitfields contained in the member I called typeData. How this can be done is explained in the article and is far too much to repeat here.

If you have problems with them anyway, ask a new question.