# Using legacy C code with autodifferentiation

**URL:** <https://discourse.julialang.org/t/using-legacy-c-code-with-autodifferentiation/132548>\
**Category:** General Usage\
**Tags:** binarybuilder, c\
**Created:** [September 22, 2025, 1:21am UTC](https://discourse.julialang.org/t/using-legacy-c-code-with-autodifferentiation/132548 "2025-09-22T01:21:17Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![marcobonici](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/marcobonici/32/20549_2.png) [@marcobonici](https://discourse.julialang.org/u/marcobonici)\
**Post date:** [September 22, 2025, 1:21am UTC](https://discourse.julialang.org/t/using-legacy-c-code-with-autodifferentiation/132548/1 "2025-09-22T01:21:17Z")

</div>

Hello,  
I am asking for some general guidance on the following task,  
There is a legacy code, written in C, that I would like to use directly in Julia. Ideally, I would like to be able to differentiate it as well (the code can be found [here](https://github.com/lesgourg/class_public) ).

So, my questions are:

- which tools should I be using to write a Julia-wrapper? Clang.jl?
- Assuming the first step work, how difficult would it be to differentiate it with Enzyme? Which constraint does this put on how the original code and the wrapper must be written?

Thanks in advance!

---

<div class="post-metadata">

**Author:** ![hersle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hersle/32/211689_2.png) [@hersle](https://discourse.julialang.org/u/hersle)\
**Post date:** [October 28, 2025, 11:19am UTC](https://discourse.julialang.org/t/using-legacy-c-code-with-autodifferentiation/132548/2 "2025-10-28T11:19:12Z")

</div>

Hi Marco!

I made the lightweight wrapper [CLASS.jl](https://github.com/hersle/CLASS.jl) package to simplify comparisons to [SymBoltz.jl](https://github.com/hersle/SymBoltz.jl). Feel free to check it out and change it around. Check `test/` for some simple examples and [here](https://hersle.github.io/SymBoltz.jl/dev/comparison/) (expand “Setup”) for a more complex one. It is structured like a problem/solution interface fairly generically around CLASS’ input/output structure.

Right now it requires you to point it to a local CLASS binary. It would be much more elegant to automatically compile it at installation or something.

I am not sure about differentiability, though.

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [October 28, 2025, 11:42am UTC](https://discourse.julialang.org/t/using-legacy-c-code-with-autodifferentiation/132548/3 "2025-10-28T11:42:54Z")

</div>

[Base Julia](https://docs.julialang.org/en/v1/manual/calling-c-and-fortran-code/) is technically enough for calling C shared libraries, though packages can help. [Enzyme](https://github.com/EnzymeAD/Enzyme) works on LLVM so you could use it directly on C. I haven’t seen a tutorial on Enzyme for Julia calling external code, but I’ve heard it’s possible (not necessarily implemented) if the LLVM IR is there. I’d suggest changing your topic’s title to mention autodifferentiation of Julia wrapping C, get more experienced eyes on this.

---

<div class="post-metadata">

**Author:** ![hersle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hersle/32/211689_2.png) [@hersle](https://discourse.julialang.org/u/hersle)\
**Post date:** [October 28, 2025, 2:18pm UTC](https://discourse.julialang.org/t/using-legacy-c-code-with-autodifferentiation/132548/4 "2025-10-28T14:18:17Z")

</div>

Just noting down some resources I found on using Enzyme through external calls:

- [Calling C Code with Automatic Differentiation in Julia](https://discourse.julialang.org/t/calling-c-code-with-automatic-differentiation-in-julia/129503)
- [Is it possible to use autodiff on an external program?](https://discourse.julialang.org/t/is-it-possible-to-use-autodiff-on-an-external-program/108475)
- [External C Libraries and Runtime Dynamic Linking `dlopen` Not Picked Up by Enzyme · Issue #2452 · EnzymeAD/Enzyme.jl · GitHub](https://github.com/EnzymeAD/Enzyme.jl/issues/2452)

---

<div class="post-metadata">

**Author:** ![hersle](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/hersle/32/211689_2.png) [@hersle](https://discourse.julialang.org/u/hersle)\
**Post date:** [October 28, 2025, 4:31pm UTC](https://discourse.julialang.org/t/using-legacy-c-code-with-autodifferentiation/132548/5 "2025-10-28T16:31:56Z")

</div>

To differentiate through CLASS and make it compatible with Enzyme, should one perhaps look to modify it so there is a pure C function that one can `ccall` from Julia (like [here](https://discourse.julialang.org/t/calling-c-code-with-automatic-differentiation-in-julia/129503/6)) to return the desired output as a function of some given input parameters? Maybe something like this:

```C
void output_from_input(double *output, double *input) {
   // populate output from input
}

```

If so, that would require circumventing the standard interface with `*.ini` input configuration files and `*.dat` output data files.

I think it would be very interesting to try to start with something trivial, say just computing \Omega\_{c0}(\omega\_{c0}) = \omega\_{c0}/h^2 as a function of \omega\_{c0} (and some fixed h). Then, if that works, one could try to include more parameters and ramp up autodiff module-by-module (background, thermodynamics, perturbations, …) and ultimately get the C\_l for the CMB as a function of some parameters or something similar.
