# Cast C struct to the same C struct but from another zig module

**URL:** <https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705>\
**Category:** Help\
**Tags:** c\
**Created:** [July 14, 2026, 10:30am UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705 "2026-07-14T10:30:19Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![ashley.h](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/bcef8e/32.png) [@ashley.h](https://ziggit.dev/u/ashley.h)\
**Post date:** [July 14, 2026, 10:30am UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/1 "2026-07-14T10:30:19Z")

</div>

I don’t know what tool I really need but I would like (to shoot my leg again) and just have force cast

So I have two C libraries (both of which I independently use) and one of them exposes API which takes as parameter type from another one

```c
//lib1.h
struct lib1_struct {...}

```

```c
//lib2.h
#include <lib1.h>
void lib2_func(lib1_struct);

```

I have two modules added via translate-c so in the end I have something like this in my zig file:

```zig
const lib1 = @import("lib1");
const lib2 = @import("lib2");

const tmp = lib1.lib1_struct {...};
lib2.lib2_func(tmp); // Error expected ...lib2.lib1_struct but got lib1.lib1_struct

```

I essentially know they are the same thing but can’t tell that to compiler

---

<div class="post-metadata">

**Author:** ![vulpesx](https://ziggit.dev/user_avatar/ziggit.dev/vulpesx/32/3989_2.png) [@vulpesx](https://ziggit.dev/u/vulpesx)\
**Post date:** [July 14, 2026, 10:38am UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/2 "2026-07-14T10:38:22Z")

</div>

it would be safe to ptr/bit cast them if they are c/extern structs with the same layout.

But ideally you shouldn’t have duplicate translated headers in the first place.

---

<div class="post-metadata">

**Author:** ![invlpg](https://ziggit.dev/letter_avatar_proxy/v4/letter/i/13edae/32.png) [@invlpg](https://ziggit.dev/u/invlpg)\
**Post date:** [July 14, 2026, 11:45am UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/4 "2026-07-14T11:45:29Z")

</div>

Why not have just one `translate-c` module?

```c
// c.h
#include <lib1.h>
#include <lib2.h>

```

```zig
const c = @import("c");

```

That way there’d only be one type.

---

<div class="post-metadata">

**Author:** ![ashley.h](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/bcef8e/32.png) [@ashley.h](https://ziggit.dev/u/ashley.h)\
**Post date:** [July 14, 2026, 12:17pm UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/5 "2026-07-14T12:17:27Z")

</div>

> [@invlpg](#):
>
> Why not have just one `translate-c` module?

1. Unfortunately:

```c
//lib1.zig
#define DISABLE_THING
#include <lib1.h>

```

```c
//lib2.zig
// #define DISABLE_THING will disable thing in lib1 but also
// will disable thing in lib2 which I need(because it looks on what is inside lib1)
// And yes it is actually safe... Just a bad design of two libs
#include <lib1.h>
#include <lib2.h>

```

1. I don’t need lib2 in all the places but it is just an autocomplete issue

---

<div class="post-metadata">

**Author:** ![ashley.h](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/bcef8e/32.png) [@ashley.h](https://ziggit.dev/u/ashley.h)\
**Post date:** [July 14, 2026, 12:18pm UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/6 "2026-07-14T12:18:17Z")

</div>

`@ptrCast` does work but not `@bitCast`

---

<div class="post-metadata">

**Author:** ![QuaternionWake](https://ziggit.dev/user_avatar/ziggit.dev/quaternionwake/32/6355_2.png) [@QuaternionWake](https://ziggit.dev/u/QuaternionWake)\
**Post date:** [July 14, 2026, 1:55pm UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/7 "2026-07-14T13:55:21Z")

</div>

Could you not do

```c
#include <lib2.h>
#define DISABLE_THING
#include <lib1.h>

```

or

```c
#define DISABLE_THING
#include <lib1.h>
#undef DISABLE_THING
#include <lib2.h>

```

If neither of those works then a `@bitCast()` or `@ptrCast()` are probably the best option.

Alternatively though, you can also try to to write your own bindings and go around `translate-c` altogether.

```zig
extern "lib1" lib1_foo(arg1: c_int, arg2: lib1_SomeStruct) void;
extern "lib2" lib2_bar() lib1_SomeStruct;

const lib1_SomeStruct = extern struct {
    field1: c_int,
    field2: [*]c_char,
};

```

---

<div class="post-metadata">

**Author:** ![ashley.h](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/bcef8e/32.png) [@ashley.h](https://ziggit.dev/u/ashley.h)\
**Post date:** [July 14, 2026, 8:50pm UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/8 "2026-07-14T20:50:59Z")

</div>

> [@QuaternionWake](#):
>
> ```zig
> #define DISABLE_THING
> #include <lib1.h>
> #undef DISABLE_THING
> #include <lib2.h>
> 
> ```

Well, I would like to do it but lib2 actually looks to a thing which is conditionally defined inside lib1 so it is more something like:

```c

//lib1.h
#ifndef DISABLE_THING
    #define THING_AVAILABLE
    void thing() {...}
#endif

//lib2.h
#ifdef THING_AVAILABLE
    void some_func() { // The only thing from lib2 I need at all :)
         thing();
    }
#endif

```

And so I need both versions of lib1 both with disabled and enabled thing. So I yeah, inherited from C dependency hell…

---

<div class="post-metadata">

**Author:** ![QuaternionWake](https://ziggit.dev/user_avatar/ziggit.dev/quaternionwake/32/6355_2.png) [@QuaternionWake](https://ziggit.dev/u/QuaternionWake)\
**Post date:** [July 14, 2026, 9:00pm UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/9 "2026-07-14T21:00:56Z")

</div>

I’m becoming _awfully_ curious what two libraries it is that you are using that do things line that.

edit: And even MORE so how it is possible that using those libraries like that is safe!

---

<div class="post-metadata">

**Author:** ![ashley.h](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/bcef8e/32.png) [@ashley.h](https://ziggit.dev/u/ashley.h)\
**Post date:** [July 14, 2026, 9:22pm UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/10 "2026-07-14T21:22:26Z")

</div>

Well

> [@QuaternionWake](#):
>
> I’m becoming _awfully_ curious what two libraries it is that you are using that do things line that.

It is a noname extension to a noname “engine” on SDL2 written in very strange state of mind. Like if there is no THING feature in original lib why to even define function used only with a THING? Which is great idea but awfully implemented…

> [@QuaternionWake](#):
>
> edit: And even MORE so how it is possible that using those libraries like that is safe!

That func in lib2 generally gives you almost static list of requirements (which you than need to check). Nothing special and it doesn’t depend much on anything except on data returned from lib1 (which in turn also very self-containing). So it would be safe to use the func from lib1 even with disabled lib1 (except it is all just not defined than…)

---

<div class="post-metadata">

**Author:** ![ashley.h](https://ziggit.dev/letter_avatar_proxy/v4/letter/a/bcef8e/32.png) [@ashley.h](https://ziggit.dev/u/ashley.h)\
**Post date:** [July 14, 2026, 9:28pm UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/11 "2026-07-14T21:28:11Z")

</div>

As said in one of previous messages `@bitCast` doesn’t work even though they have identical layout but well `@ptrCast` works so hacky thing is possible:

1. get pointer
2. cast pointer
3. de-reference pointer

```zig
var tmp: lib1.struct = {...}
@as(*lib2.struct, @ptrCast(&tmp)).*

```

Thanks all for helping!

---

<div class="post-metadata">

**Author:** ![floooh](https://ziggit.dev/user_avatar/ziggit.dev/floooh/32/2989_2.png) [@floooh](https://ziggit.dev/u/floooh)\
**Post date:** [July 15, 2026, 7:22am UTC](https://ziggit.dev/t/cast-c-struct-to-the-same-c-struct-but-from-another-zig-module/16705/12 "2026-07-15T07:22:34Z")

</div>

Slightly related, but I wished that more languages would offer optional structural typing, e.g. an annotation on struct declarations that makes two independently defined structs with different names but with the same ‘interior layout’ assignable to each other without an explicit cast.
