# Using C struct in Julia without creating same struct in Julia again

**URL:** <https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639>\
**Category:** General Usage\
**Tags:** question, struct, c\
**Created:** [August 18, 2021, 10:46pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639 "2021-08-18T22:46:21Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![m\_yasinhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/m_yasinhan/32/28315_2.png) [@m\_yasinhan](https://discourse.julialang.org/u/m_yasinhan)\
**Post date:** [August 18, 2021, 10:46pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/1 "2021-08-18T22:46:21Z")

</div>

Hi, we have `ccall` to call any c function. But, if the function we want to call has a parameter which is non-primitive type such as a struct, do we always have to create same struct in Julia? For example, I have this c code.

```nohighlight
#include <StaticLibrary.h>

typedef struct 
{
    struct StaticLibrary* thing;
} Bar;

typedef struct 
{
    Bar b;
    char* t;
} Foo;

void myFunction(Foo* foo, char t*)
{
//code
}

```

I want to use myFunction with `ccall` I generate a shared library from my C code, and I use it. it works. But I need to create same structs in Julia too. so, Why? I can write same function in Julia too! And I also have a StaticLibrary and `struct StaticLibrary* thing;` is coming from there, I don’t have the declaration of that struct for creating it in julia. I hope, I could explain myself… Sorry for my English. So my question is “do we always have to create same struct in Julia to pass argument?”

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [August 18, 2021, 11:52pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/2 "2021-08-18T23:52:24Z")

</div>

If the interface of your C code is all about passing handles/opaque pointers, then there is no need to map those underlying structures on the Julia side. You could make everything a `Ptr{Cvoid}` or define a opaque singleton struct `mutable struct Foo end` and use `Ptr{Foo}`.

---

<div class="post-metadata">

**Author:** ![m\_yasinhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/m_yasinhan/32/28315_2.png) [@m\_yasinhan](https://discourse.julialang.org/u/m_yasinhan)\
**Post date:** [August 19, 2021, 10:32am UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/3 "2021-08-19T10:32:19Z")

</div>

I tried `mutable struct Foo end` and using `Ptr{Foo}` . but I get an Error. It is Julia Part:

```nohighlight
using Libdl
libJulia3D = dlopen("../build/libJulia3D.so")
    
j3d_window_create = dlsym(libJulia3D, "j3d_window_create")
j3d_window_initialize = dlsym(libJulia3D, "j3d_window_initialize")
j3d_window_destroy = dlsym(libJulia3D, "j3d_window_destroy")

mutable struct J3DWindow end

function init(window, width, height, title)
    ccall(j3d_window_create, Cchar, (Ptr{J3DWindow}, Csize_t, Csize_t, Cstring), window, width, height, title)
end

#Main
window = J3DWindow()

init(window, 600, 400, "abc")

```

and my c part is:

```nohighlight
JULIA3D_CORE struct J3DWindow
{
    GLFWwindow* m_window;
    size_t m_width;
    size_t m_height;
    char* m_title;
};

JULIA3D_CORE bool j3d_window_create(J3DWindow* window, size_t width, size_t height, const char* title)
{
    window->m_width = width;
    window->m_height = height;
    window->m_title = title;
}

```

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [August 19, 2021, 10:33am UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/4 "2021-08-19T10:33:46Z")

</div>

That’s because `J3DWindow` in C is not an opaque pointer.

---

<div class="post-metadata">

**Author:** ![m\_yasinhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/m_yasinhan/32/28315_2.png) [@m\_yasinhan](https://discourse.julialang.org/u/m_yasinhan)\
**Post date:** [August 19, 2021, 10:41am UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/5 "2021-08-19T10:41:57Z")

</div>

```nohighlight
typedef JULIA3D_CORE struct _J3DWindow
{
    GLFWwindow* m_window;
    size_t m_width;
    size_t m_height;
    char* m_title;
} *J3DWindow;

JULIA3D_CORE bool j3d_window_create(J3DWindow window, size_t width, size_t height, const char* title)
{
    window->m_width = width;
    window->m_height = height;
    window->m_title = title;
}

```

now, is it opaque right? if not, can you explain?

---

<div class="post-metadata">

**Author:** ![m\_yasinhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/m_yasinhan/32/28315_2.png) [@m\_yasinhan](https://discourse.julialang.org/u/m_yasinhan)\
**Post date:** [August 19, 2021, 10:51am UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/6 "2021-08-19T10:51:01Z")

</div>

ohh sir, I changed  
`ccall(j3d_window_create, Cchar, (Ptr{J3DWindow}, Csize_t, Csize_t, Cstring), window, width, height, )` part as `ccall(j3d_window_create, Cchar, (` **Ref** `{J3DWindow}, Csize_t, Csize_t, Cstring), window, width, height, )` it works, thanks for all your answers.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [August 19, 2021, 12:11pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/7 "2021-08-19T12:11:46Z")

</div>

No.

[https://stackoverflow.com/questions/7553750/what-is-an-opaque-pointer-in-c](https://stackoverflow.com/questions/7553750/what-is-an-opaque-pointer-in-c)

In short, you should not expose the definition of `_J3DWindow` in the header file. To work with opaque pointers, `static_cast`/`reinterpret_cast`/C-style cast should be correctly used in the function definition.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [August 19, 2021, 12:15pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/8 "2021-08-19T12:15:05Z")

</div>

> [@m\_yasinhan](#):
>
> ohh sir, I changed  
> `ccall(j3d_window_create, Cchar, (Ptr{J3DWindow}, Csize_t, Csize_t, Cstring), window, width, height, )` part as `ccall(j3d_window_create, Cchar, (` **Ref** `{J3DWindow}, Csize_t, Csize_t, Cstring), window, width, height, )` it works, thanks for all your answers.

This is not right. `Ref{J3DWindow}`/`Ptr{J3DWindow}` is a pointer to `J3DWindow` which is a pointer to `_J3DWindow`. But your C function expects a pointer to `_J3DWindow`.

---

<div class="post-metadata">

**Author:** ![m\_yasinhan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/m_yasinhan/32/28315_2.png) [@m\_yasinhan](https://discourse.julialang.org/u/m_yasinhan)\
**Post date:** [August 19, 2021, 12:32pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/9 "2021-08-19T12:32:09Z")

</div>

yeah you are right but Ptr{J3DWindow} in Julia is \_J3DWindow\* in C. Yeah it is little bit confusing because of names.

---

<div class="post-metadata">

**Author:** ![Gnimuc](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gnimuc/32/2194_2.png) [@Gnimuc](https://discourse.julialang.org/u/Gnimuc)\
**Post date:** [August 19, 2021, 12:35pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/10 "2021-08-19T12:35:13Z")

</div>

> [@m\_yasinhan](#):
>
> Yeah it is little bit confusing because of names.

Indeed. 😅

BTW, you may find [Clang.jl](https://github.com/JuliaInterop/Clang.jl) is useful for auto-generating Julia bindings from C headers.

---

<div class="post-metadata">

**Author:** ![krrutkow](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/krrutkow/32/9138_2.png) [@krrutkow](https://discourse.julialang.org/u/krrutkow)\
**Post date:** [August 19, 2021, 2:11pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/11 "2021-08-19T14:11:55Z")

</div>

You might also want to look at using [CBinding.jl](https://github.com/analytech-solutions/CBinding.jl) for more faithfully preserved names and types in the bindings, so you might have fewer surprises.

---

<div class="post-metadata">

**Author:** ![AzizAlqasem](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/azizalqasem/32/38850_2.png) [@AzizAlqasem](https://discourse.julialang.org/u/AzizAlqasem)\
**Post date:** [August 17, 2022, 7:00pm UTC](https://discourse.julialang.org/t/using-c-struct-in-julia-without-creating-same-struct-in-julia-again/66639/12 "2022-08-17T19:00:39Z")

</div>

I have a similar question to @m_yasinhan, with a slight differences.

The function that I want to call from C is:  
`usb_dev_handle* __stdcall xxusb_device_open(struct usb_device *dev);`

Where `usb_device` is defined as:

```julia
struct usb_device {
  struct usb_device *next, *prev;

  char filename[LIBUSB_PATH_MAX];

  struct usb_bus *bus;

  struct usb_device_descriptor descriptor;
  struct usb_config_descriptor *config;

  void *dev; /* Darwin support */

  unsigned char devnum;

  unsigned char num_children;
  struct usb_device **children;
};

```

In Julia, I defined two structs as:

```julia
mutable struct UDH end
mutable struct UD end
ud = UD()

```

Then, I call the c funtion as:

```julia
ccall((:xxusb_device_open, "libxxusb.dll"), Ref{UDH}, (Ref{UD},), ud)

#Also tried this
#ccall((:xxusb_device_open, "libxxusb.dll"), Ptr{UDH}, (Ptr{UD},), ud)

```

This way has always worked with me except for this function/struct where I get the following error:

```julia
Please submit a bug report with steps to reproduce this fault, and any error messages that follow (in their entirety). Thanks.
Exception: EXCEPTION_ACCESS_VIOLATION at 0x5b503d85 -- usb_set_configuration at C:\WINDOWS\SYSTEM32\libusb0.dll (unknown line)
in expression starting at REPL[5]:1
usb_set_configuration at C:\WINDOWS\SYSTEM32\libusb0.dll (unknown line)
xxusb_device_open at C:\WINDOWS\SYSTEM32\libxxusb.dll (unknown line)
top-level scope at .\REPL[5]:1
jl_fptr_args at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2016
_jl_invoke at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2247 [inlined]
jl_invoke at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2254
jl_toplevel_eval_flex at /cygdrive/c/buildbot/worker/package_win32/build/src\toplevel.c:876
jl_toplevel_eval_flex at /cygdrive/c/buildbot/worker/package_win32/build/src\toplevel.c:830
jl_toplevel_eval at /cygdrive/c/buildbot/worker/package_win32/build/src\toplevel.c:894 [inlined]
jl_toplevel_eval_in at /cygdrive/c/buildbot/worker/package_win32/build/src\toplevel.c:944
eval at .\boot.jl:373 [inlined]
eval_user_input at C:\buildbot\worker\package_win32\build\usr\share\julia\stdlib\v1.7\REPL\src\REPL.jl:150
repl_backend_loop at C:\buildbot\worker\package_win32\build\usr\share\julia\stdlib\v1.7\REPL\src\REPL.jl:246
start_repl_backend at C:\buildbot\worker\package_win32\build\usr\share\julia\stdlib\v1.7\REPL\src\REPL.jl:231
#run_repl#47 at C:\buildbot\worker\package_win32\build\usr\share\julia\stdlib\v1.7\REPL\src\REPL.jl:364
run_repl at C:\buildbot\worker\package_win32\build\usr\share\julia\stdlib\v1.7\REPL\src\REPL.jl:351
jl_fptr_args at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2016
_jl_invoke at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2228 [inlined]
jl_apply_generic at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2429
#936 at .\client.jl:394
_jfptr_YY.936_32814.clone_1 at C:\Users\alqasem.2\AppData\Local\Programs\Julia-1.7.3\lib\julia\sys.dll (unknown line)
_jl_invoke at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2228 [inlined]
jl_apply_generic at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2429
jl_apply at /cygdrive/c/buildbot/worker/package_win32/build/src\julia.h:1788 [inlined]
jl_f__call_latest at /cygdrive/c/buildbot/worker/package_win32/build/src\builtins.c:757
#invokelatest#2 at .\essentials.jl:716 [inlined]
invokelatest at .\essentials.jl:714 [inlined]
run_main_repl at .\client.jl:379
exec_options at .\client.jl:309
_start at .\client.jl:495
_jfptr__start_34933.clone_1 at C:\Users\alqasem.2\AppData\Local\Programs\Julia-1.7.3\lib\julia\sys.dll (unknown line)
_jl_invoke at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2228 [inlined]
jl_apply_generic at /cygdrive/c/buildbot/worker/package_win32/build/src\gf.c:2429
jl_apply at /cygdrive/c/buildbot/worker/package_win32/build/src\julia.h:1788 [inlined]
true_main at /cygdrive/c/buildbot/worker/package_win32/build/src\jlapi.c:559
jl_repl_entrypoint at /cygdrive/c/buildbot/worker/package_win32/build/src\jlapi.c:701
jl_load_repl at /cygdrive/c/buildbot/worker/package_win32/build/cli\loader_lib.c:220
mainCRTStartup at /cygdrive/c/buildbot/worker/package_win32/build/cli\loader_exe.c:42
BaseThreadInitThunk at C:\WINDOWS\System32\KERNEL32.DLL (unknown line)
RtlGetAppContainerNamedObjectPath at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line)
RtlGetAppContainerNamedObjectPath at C:\WINDOWS\SYSTEM32\ntdll.dll (unknown line)
Allocations: 2722 (Pool: 2717; Big: 5); GC: 0

```

Does anyone know why this cannot work, and how to fix it?

Thank you
