Thread overview
Use C struct declaration without knowing definition
Jul 25, 2019
Ben Ogles
Jul 25, 2019
Ali Çehreli
Jul 25, 2019
Ben Ogles
July 25, 2019
Is there a way to use a C header that contains a struct declaration but no definition?

For example, the C header may contain:

typedef struct some_type_s some_type;

Which is only fully defined in the implementing C file:

struct some_type_s { ... };

I am trying to wrap the header in D:

extern(C)
{
  struct some_type_s;
  alias some_type = some_type_s;
}

And then use it in another D file:

some_type s;

But dmd does not know the size of the struct so it can't compile. Is there a work around to this other than moving the struct definition into the C header file?

July 24, 2019
On 07/24/2019 05:35 PM, Ben Ogles wrote:
> Is there a way to use a C header that contains a struct declaration but
> no definition?
>
> For example, the C header may contain:
>
> typedef struct some_type_s some_type;
>
> Which is only fully defined in the implementing C file:
>
> struct some_type_s { ... };

And that type is traded as pointer to some_type on the C API, right? Usually there is a factory method that returns a pointer to a dynamically allocated object.

> I am trying to wrap the header in D:
>
> extern(C)
> {
>    struct some_type_s;
>    alias some_type = some_type_s;
> }
>
> And then use it in another D file:
>
> some_type s;
>
> But dmd does not know the size of the struct so it can't compile. Is
> there a work around to this other than moving the struct definition into
> the C header file?

Indeed. The only option is to use some_type* on the D API as well:

extern(C) {
  struct S;
  S* C_API_allocate();
  void C_API(const(S) *);
}

// D API
void foo(S* s)  {
  C_API(s);
}

void main() {
  auto s = C_API_allocate();
  foo(s);
}

Note: That program fails to link because C API functions are missing definitions.

You can wrap the pointer i a D struct and dispatch member function calls to the C API.

Ali

July 25, 2019
On Thursday, 25 July 2019 at 01:08:48 UTC, Ali Çehreli wrote:
> And that type is traded as pointer to some_type on the C API, right? Usually there is a factory method that returns a pointer to a dynamically allocated object.

Correct, there is a function prototype that returns a dynamically allocated instance of the struct.

> Indeed. The only option is to use some_type* on the D API as well:
>
> extern(C) {
>   struct S;
>   S* C_API_allocate();
>   void C_API(const(S) *);
> }
>
> // D API
> void foo(S* s)  {
>   C_API(s);
> }
>
> void main() {
>   auto s = C_API_allocate();
>   foo(s);
> }

This makes sense. I can only deal with pointers to dynamically allocated instances of the struct since there is no way to know the size of the struct at compile time. Now that I think about it, this would be the case whether or not I was using D at all.

Thanks for your help!