# Running external c-code function in MTK model

**URL:** https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265
**Category:** Modelling & Simulations
**Created:** [December 1, 2025, 8:06pm UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265 "2025-12-01T20:06:48Z")
**Posts on this page:** 8
**Page:** 1

<div class="post-metadata">

### Author: ![JulianMs](https://avatars.discourse-cdn.com/v4/letter/j/f19dbf/32.png) [@JulianMs](https://discourse.julialang.org/u/JulianMs)
#### Post date: [December 1, 2025, 8:06pm UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265/1 "2025-12-01T20:06:48Z")

</div>

Hi community,

I am new to Julia and in particular MTK.  
My goal is to simulate a battery cell and couple it with external C-code to run an extended Kalman filter for SOC estimation at a fixed sampling rate.

Somehow this kind of problem does not seem to be something many people deal with in Julia, at least documentation is very limited here. I guess FMU would be a possibility. However, the FMI.jl package hasn’t beed updated for a while and so far it does not support array inputs/outputs (which I ultimately need). Even then, how would the finite sampling time be realized, using events?

Is there another possibility to run external C-code functions using ccall and add the call at a certain rate to a symbolic system description? Ideally connecting it using inputs and outputs of the MTK system?

I would be grateful for general advice on best practices here.

Thanks in advance!

Edit: Just saw that FMI.jl has been updated 2 weeks ago.

---

<div class="post-metadata">

### Author: ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)
#### Post date: [December 1, 2025, 9:28pm UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265/2 "2025-12-01T21:28:57Z")

</div>

Just register the function. See `@register_symbolic`

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [December 2, 2025, 6:03am UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265/3 "2025-12-02T06:03:07Z")

</div>

> [@JulianMs](#):
>
> to run an extended Kalman filter

this is a discrete-time system and it requires the in-development support for synchronous programming

[![](https://global.discourse-cdn.com/julialang/original/3X/6/0/60aed34bd0c2bd1fa8579fbcdfb9bd3b9b2e8f97.jpeg "Synchronous Systems in ModelingToolkit | Chung | JuliaCon Global 2025") ](https://www.youtube.com/watch?v=emDc42Q-pTo)

which is not quite available yet. You can still perform state estimation for MTK models in other ways, for example

- [GitHub - baggepinnen/LowLevelParticleFiltersMTK.jl: An interface for state estimation using LowLevelParticleFilters on ModelingToolkit models](https://github.com/baggepinnen/LowLevelParticleFiltersMTK.jl) : Interface package between MTK and state estimation
- [static\_kalman/juliac at main · baggepinnen/static\_kalman · GitHub](https://github.com/baggepinnen/static_kalman/tree/main/juliac) : A demo of static compilation of an MTK model and julia code for state estimation

---

<div class="post-metadata">

### Author: ![JulianMs](https://avatars.discourse-cdn.com/v4/letter/j/f19dbf/32.png) [@JulianMs](https://discourse.julialang.org/u/JulianMs)
#### Post date: [December 2, 2025, 10:18am UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265/4 "2025-12-02T10:18:33Z")

</div>

Thanks, this seems to work!

---

<div class="post-metadata">

### Author: ![JulianMs](https://avatars.discourse-cdn.com/v4/letter/j/f19dbf/32.png) [@JulianMs](https://discourse.julialang.org/u/JulianMs)
#### Post date: [December 2, 2025, 10:22am UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265/5 "2025-12-02T10:22:40Z")

</div>

That’s an interesting talk! Is there a timeline when this feature is to be published? How does this relate to tutorials → discrete\_system (sorry I cannot add a link here)? Until the feature in the presentation is released, can I use events instead, specifically make ccalls in an event callback?

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [December 2, 2025, 10:31am UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265/6 "2025-12-02T10:31:21Z")

</div>

> [@JulianMs](#):
>
> How does this relate to tutorials → discrete\_system

This is only for systems that are only discrete time, no continuous time dynamics.

> [@JulianMs](#):
>
> Until the feature in the presentation is released, can I use events instead, specifically make ccalls in an event callback?

Yes, it’s slightly cumbersome but not too bad if you have a single discrete-time component only

---

<div class="post-metadata">

### Author: ![JulianMs](https://avatars.discourse-cdn.com/v4/letter/j/f19dbf/32.png) [@JulianMs](https://discourse.julialang.org/u/JulianMs)
#### Post date: [December 4, 2025, 6:47am UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265/7 "2025-12-04T06:47:56Z")

</div>

Alright, i have a follow-up question.

I had a minimal example running where a continuous event would directly call a c function that was registered symbolic.

Now, my C-code wrapper has structures as inputs and outputs, i.e. I need to set those first, before doing the actual C-call.

This is my event inside @mtkmodel environment

```julia
@continuous_events begin
        [timer_wrapper ~ 1.0] =>
            [
                timer_wrapper ~ 0.0,
                soc_bat_est ~ wrapper_execute!(i_set, Tuple([Pre(getproperty(base_ecm, Symbol("cells_$i")).u_cg) for i in 1:n_series]))
            ]
    end

```

This is the Wrapper function

```julia
function wrapper_execute!(i_set::Real, u_cell::NTuple{NUM_CELLS, Real})
    inputs = WrapperInputs(current = Cfloat(i_set),
                           cellVoltages = ntuple(j -> Cfloat(u_cell[j]), NUM_CELLS))
    outputs = WrapperOutputs()
    retval = @ccall LIB_PATH.wrapper_execute(Ref(inputs)::Ptr{WrapperInputs},
                                           Ref(outputs)::Ptr{WrapperOutputs})::WrapperError

    return outputs.socMean
end

@register_symbolic wrapper_execute!(i_set, u_cell)

```

(instead of

```julia-auto
wrapper_execute(val1, val2) = ... # ccall with val1 and val2 as doubles
@register_symbolic wrapper_execute(val1, val2)

```

)

Somehow, using the struct arguments this does not work, because the ccall in this case does not receive numeric values, but symbolic. What am I missing? Is there a workaround?

Cheers

---

<div class="post-metadata">

### Author: ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)
#### Post date: [December 4, 2025, 8:59am UTC](https://discourse.julialang.org/t/running-external-c-code-function-in-mtk-model/134265/8 "2025-12-04T08:59:08Z")

</div>

Using a continuous event is probably suboptimal if you want a periodic execution, this is what discrete periodic callbacks are for. Having said that, you should hopefully be able to use what you have if you do

```julia-auto
@register_symbolic wrapper_execute!(i_set::Real, u_cell::NTuple{NUM_CELLS, Real})

```
