# Changing array values in place when embedding in C++

**URL:** <https://discourse.julialang.org/t/changing-array-values-in-place-when-embedding-in-c/77248>\
**Category:** General Usage\
**Tags:** question, embedding, c\
**Created:** [March 1, 2022, 3:52pm UTC](https://discourse.julialang.org/t/changing-array-values-in-place-when-embedding-in-c/77248 "2022-03-01T15:52:41Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![cloclo](https://avatars.discourse-cdn.com/v4/letter/c/d26b3c/32.png) [@cloclo](https://discourse.julialang.org/u/cloclo)\
**Post date:** [March 1, 2022, 3:52pm UTC](https://discourse.julialang.org/t/changing-array-values-in-place-when-embedding-in-c/77248/1 "2022-03-01T15:52:42Z")

</div>

Hello,

I may be missing the obvious here, hopefully someone can point it out to me: when calling a custom julia function from C++ passing an array of doubles, the array values should be changed in place but is not.

For example, the Julia function definition

```julia
Base.@ccallable function square_array(x::Ptr{Cdouble}, N::Cintmax_t)::Cint
    x = array_wrap(x, (N))
    x .*= 2
    0
end

```

The corresponding call in C++

```cpp
#include <iostream>
#include <julia.h>

JULIA_DEFINE_FAST_TLS()

int main()
{
    jl_init_with_image__threading(NULL, "/path/to/image.so");
    {
        jl_function_t* func = jl_get_function(jl_main_module, "square_array");
        if(func) {
            jl_value_t** args;
            const int dataN = 2;
            const int nargs = 2;
            JL_GC_PUSHARGS(args, nargs);

            jl_value_t* double_type_1d = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
            jl_array_t* x = jl_alloc_array_1d(double_type_1d, dataN);

            double* xData = (double*)jl_array_data(x);
            xData[0] = 1.3;
            xData[1] = 4.6;

            for(int i = 0; i < dataN; ++i) {
                std::cout << i << ": " << xData[i] << std::endl;
            }

            args[0] = (jl_value_t*)x;
            args[1] = jl_box_int64(dataN);

            std::cout << "starting test..." << std::endl;
            jl_value_t* val = jl_call(func, args, nargs);
            JL_GC_PUSH1(&val);
            
            std::cout << "test finished: " << val << std::endl;

            for(int i = 0; i < dataN; ++i) {
                std::cout << i << ": " << xData[i] << std::endl;
            }

            // cleanup
            JL_GC_POP();

        } else {
            std::cout << "Function square_array() not found!" << std::endl;
        }
    }
    jl_atexit_hook(0);
}

```

However looking at a similar example in C (from [C/eval\_julia\_personal\_function\_array\_args/embed\_example.c · master · Jamil\_Projects / Embedded\_Julia / Julia\_embed · GitLab](https://gitlab.com/jamil_projects/embedded_julia/julia_embed/-/blob/master/C/eval_julia_personal_function_array_args/embed_example.c)), the following will make the change in place.

```cpp
#include <julia.h>

//JULIA_DEFINE_FAST_TLS() // only define this once, in an executable (not in a shared library) if you want fast code.

#include <stdio.h>

int main(int argc, char *argv[])
{
 
    printf("THIS CODE IS TO SQUARE ALL ELEMENTS IN AN ARRAY AND RETURN THE NEW ARRAY IN A JULIA MODULE");
    /* required: setup the Julia context */
    jl_init();

    /* create a 1D array of length 100 */

    double length = 5;
    double *existingArray = (double*)malloc(sizeof(double)*length);

    /* create a *thin wrapper* around our C array */
    jl_value_t* array_type = jl_apply_array_type((jl_value_t*)jl_float64_type, 1);
    jl_array_t *x = jl_ptr_to_array_1d(array_type, existingArray, length, 0);
    JL_GC_PUSH1(&x);

    
    /* fill in values */
    double *xData = (double*)jl_array_data(x);

    for(size_t i=0; i<jl_array_len(x); i++)
        xData[i] = i;
    printf("x = [");
    for(size_t i=0; i<jl_array_len(x); i++)
            printf("%i ", (int)xData[i]);
    printf("]\n");

    /* import `jamil_math` module from file jamil_math.jl */
    jl_eval_string("Base.include(Main, \"jamil_math.jl\")");

    /* load the module into the current stack*/
    jl_eval_string("using .jamil_math");

    /* convert the module into a C module*/
    jl_module_t* jamil_math_module = (jl_module_t *)jl_eval_string("module_math");

    /* get `square_array` function from module */
    jl_function_t *square_array = jl_get_function(jamil_math_module, "square_array");

    /* call the function */
    jl_call1(square_array, (jl_value_t*)x);

    /* print new values of x */
    printf("new values after being passed into julia function");
    printf("\nx = [");
    for (int i = 0; i < length; i++)
        printf("%.1f ", xData[i]);
    printf("]\n");
    

    JL_GC_POP();

    /* exit */
    jl_atexit_hook(0);
    
    printf("\n\n\n");

    return 0;

}

```

If I call the function from Python (similarly loading dynamically the .so/.dll), the values are changed in place as expected. Here it is in Python

```python
from ctypes import c_long, c_void_p
import numpy as np

julia_lib = "/path/to/julia/lib.so"
custom_image = "/path/to/custom/lib.so"

internal_jl = ctypes.CDLL(julia_lib)
api = ctypes.CDLL(custom_image, ctypes.RTLD_GLOBAL)

internal_jl.jl_init_with_image__threading.argtypes = [ctypes.c_char_p, ctypes.c_char_p]
internal_jl.jl_init_with_image__threading(None, bytes(custom_image, 'utf-8'))

x = 2 * np.ones(3)
api.square_array(c_void_p(x.ctypes.data), c_long(3))
print(x)
# => prints [4., 4., 4.]

```

So I can’t get my head around why the first c++ snippet code doesn’t change the value in place although it should, any idea?  
thanks!

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [March 1, 2022, 7:29pm UTC](https://discourse.julialang.org/t/changing-array-values-in-place-when-embedding-in-c/77248/2 "2022-03-01T19:29:47Z")

</div>

Toying around a bit with your code it seems `square_array` is never actually called. Checking for an exception directly after the `jl_call()` reveals a MethodError is raised. This is likely due to the fact that the `x` argument being passed is an `Array{Float64,1}` and not a `Ptr{Cdouble}` (although I don’t know the details of whether that can be made to work when embedding).

Updating the signature of `square_array` to use `x::Vector{Float64}` makes the function get called, but `array_wrap` is then unknown, but is also no longer needed as you can modify the array directly and it will get updated on the C++ side as well.

---

<div class="post-metadata">

**Author:** ![cloclo](https://avatars.discourse-cdn.com/v4/letter/c/d26b3c/32.png) [@cloclo](https://discourse.julialang.org/u/cloclo)\
**Post date:** [March 2, 2022, 7:47pm UTC](https://discourse.julialang.org/t/changing-array-values-in-place-when-embedding-in-c/77248/3 "2022-03-02T19:47:06Z")

</div>

hmmm, interesting, I completely missed that part: if you don’t mind, how did you manage to get the error message sent back to you (I couldn’t get anything with try/catch statements)?

So it looks like I need 2 functions to accommodate both cases, one for the call from Python through C (which passes `void*`), one for the call from C/C++ (which passes directly `Vector/Matrix{Float64}`).

(the `array_wrap()` is needed when the ccallable function gets a `void*` so that it can reshape to its proper/actual size - and apparently is not necessary for the C/C++ bridge to Julia through `jl_call()`)

I’ll give it a try and report back  
thanks for the insight

---

<div class="post-metadata">

**Author:** ![paulmelis](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/paulmelis/32/35063_2.png) [@paulmelis](https://discourse.julialang.org/u/paulmelis)\
**Post date:** [March 2, 2022, 8:17pm UTC](https://discourse.julialang.org/t/changing-array-values-in-place-when-embedding-in-c/77248/4 "2022-03-02T20:17:36Z")

</div>

> [@cloclo](#):
>
> hmmm, interesting, I completely missed that part: if you don’t mind, how did you manage to get the error message sent back to you (I couldn’t get anything with try/catch statements)?

You can check for exceptions on the C/C++ side with for example

```julia
if (jl_exception_occurred())
    printf("%s \n", jl_typeof_str(jl_exception_occurred()));

```

See [this section](https://docs.julialang.org/en/v1/manual/embedding/#Exceptions) for more details

---

<div class="post-metadata">

**Author:** ![cloclo](https://avatars.discourse-cdn.com/v4/letter/c/d26b3c/32.png) [@cloclo](https://discourse.julialang.org/u/cloclo)\
**Post date:** [March 4, 2022, 1:52pm UTC](https://discourse.julialang.org/t/changing-array-values-in-place-when-embedding-in-c/77248/5 "2022-03-04T13:52:46Z")

</div>

Thanks @paulmelis I confirm that you got it right: the function signature in Julia does not need to be ccallable, the Julia directly recognizes the `Vector/Matrix(Float64}`

In my case, I simply need 2 functions with different signature to call the same core code so that it can handle calls from both C++ and Python. Something like

```nohighlight
Base.@ccallable function c_double_array(x::Ptr{Cdouble}, N::Cintmax_t)::Cint
    x = array_wrap(x, (N))
    double_array(x)
end

function double_array(x)
    x .*= 2
    0
end

```
