# Passing a BigInt (mpz\_t for GMP) array to C

**URL:** https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622
**Category:** General Usage
**Created:** [December 9, 2024, 2:25pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622 "2024-12-09T14:25:06Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [December 9, 2024, 2:25pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/1 "2024-12-09T14:25:07Z")

</div>

Lately, I’ve managed to pass a BigInt to C and back ([Passing GMP variables from C(++) to Julia - #10 by Questioner](https://discourse.julialang.org/t/passing-gmp-variables-from-c-to-julia/123167/10)). Now suppose I want to generate Fibonacci numbers in C and pass them to Julia. I thought I just take the analogous code for arrays

```julia
#include<gmp.h>

void test(mpz_t* var[]) {
	mpz_init_set_ui(*var[1], 2);
}

```

but upon calling it

```julia
@ccall "./art.so".test(x::Ptr{Ref{BigInt}})::Cvoid

```

where x was

```julia
 x
2-element Vector{Ref{BigInt}}:
 Base.RefValue{BigInt}(3)
 Base.RefValue{BigInt}(3)

```

it ran, but crashed upon typing “x” and hitting enter, producing a lengthy error message.

I’d be grateful for any input on how to solve this problem.

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [December 20, 2024, 5:35pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/2 "2024-12-20T17:35:03Z")

</div>

I’ve finally found a workaround: I’m first creating an array in Julia

```julia
grr = Array{BigInt}(undef, 2)

```

then I save pointers to the elements of that array into a different array

```julia
arr = Array{Ptr{Nothing}}(undef, 2)
for j in 1:2
   arr[j] = pointer_from_objref(grr[j])
end

```

This last array is what I pass to C:

```julia
@ccall "./gmptest.so".modify2(arr::Ref{Ptr{Nothing}})::Cvoid

```

C then operates on `arr`, like in the following code:

```julia
void modify2(mpz_t* arr[]) {
	mpz_set_ui(*arr[1], 10);
}

```

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [December 20, 2024, 5:41pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/3 "2024-12-20T17:41:22Z")

</div>

Can’t you just pass `grr` to `modify2` directly? i.e.

```julia
@ccall "./gmptest.so".modify2(grr::Ptr{BigInt})::Cvoid

```

since a `Vector{BigInt}` is stored under the hood as an array of pointers to `BigInt` objects (which aren’t stored inline since they are mutable structs), and `BigInt` objects are laid out identically to `mpz_t` (so that they can be passed by reference to GMP functions).

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 5, 2025, 2:05pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/4 "2025-05-05T14:05:02Z")

</div>

Hello there,

in the post [Passing a BigInt (mpz\_t for GMP) array to C](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622) I tried in vain to pass a GMP number to C. Upon inspecting the memory, it became apparent that C stored the “chunks” of the big integer in adjacent memory blocks, whereas in Julia the number was scattered.

Firstly, it would be necessary to make the big integer accessible to C, so that passing it to C works, and receiving it also works.

But then, for speed reasons it would seem recommendable to have Julia also store the number chunks in adjacent memory blocks.

I would probably enjoy implementing this myself; the only problem is that I don’t quite know where this functionality is in the Julia code.

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 2:45pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/5 "2025-05-06T14:45:09Z")

</div>

I’ve been pointed to the right file (base/gmp.jl), but it has to be said that I don’t properly understand that code, since I don’t know many of the symbols and names therein.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [May 6, 2025, 3:32pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/6 "2025-05-06T15:32:49Z")

</div>

That code in `gmp.jl` simply passes `BigInt` objects directly to `ccall` as `Ref{BigInt}`, which should be declared as an `mpz_t*` argument (a single pointer, _not_ an array of pointers) on the C side.

That is, if you have a C function `void foo(mpz_t *arg) { .... }`, then you could call it in Julia as `@ccall mylibrary.foo(n::Ref{BigInt})::Cvoid` where `n` is a `BigInt`.

If you modify `arg` on the C side, then the changes will be visible in `n` on the Julia side.

(I said something similar in your other thread.)

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 3:39pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/7 "2025-05-06T15:39:09Z")

</div>

I’ll certainly give it a try.

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 4:03pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/8 "2025-05-06T16:03:00Z")

</div>

Allright, passing a single BigInt worked. That leaves the array case.

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 4:16pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/9 "2025-05-06T16:16:28Z")

</div>

The array case failed.

C code

```julia
void AddToS(mpz_t arr[]) {
	mpz_add_ui(arr[1], arr[1], 2);
}

```

Julia code

```julia
x = BigInt(40000000000000000000000000000000000000000000000000000000000000000000000000000000000000)

y = BigInt(40000000000000000000000000000000000000000000000000000000000000000000000000000000000000)

a = [x, y]

@ccall "gmptest.so".AddToS(a::Ptr{BigInt})::Cvoid

```

There was no effect on y or a.

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [May 6, 2025, 4:18pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/10 "2025-05-06T16:18:22Z")

</div>

> [@Questioner](#):
>
> Allright, passing a single BigInt worked. That leaves the array case.

If you have a `nums::Vector{BigInt}` in Julia, e.g. `nums = BigInt[1,2,3]`, I think you can just pass it as `Ptr{BigInt}` to a C function that takes an `mpz_t *`. That is, write a C function like:

```c
void foo(mpz_t *nums, size_t len) {
    for (size_t i = 0; i < len; ++i)
        mpz_set_ui(&nums[i], i);
}

```

and then call it as e.g.

```julia
nums = BigInt[17, 23, 51]
@ccall mylibrary.foo(nums::Ptr{BigInt}, length(nums)::Csize_t)::Cvoid

```

after which the `nums` array should contain `[0,1,2]`.

- Note that the `BigInt` values are already initialized, so we call `mpz_set_ui` not `mpz_init_set_ui`.
- Note that C indexing is 0-based, even though Julia indexing is 1-based.

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 4:19pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/11 "2025-05-06T16:19:43Z")

</div>

I’ve done basically the exact same thing, but it didn’t work.

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 4:20pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/12 "2025-05-06T16:20:29Z")

</div>

Does your code work on your system?

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [May 6, 2025, 4:20pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/13 "2025-05-06T16:20:35Z")

</div>

“Basically” exactly the same thing, or exactly the same thing? The code examples you posted above were _not_ equivalent to this.

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 4:21pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/14 "2025-05-06T16:21:00Z")

</div>

In what way was my code different? (Note that I’ve posted a new post with code!)

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [May 6, 2025, 4:23pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/15 "2025-05-06T16:23:57Z")

</div>

> [@stevengj](#):
>
> f you have a `nums::Vector{BigInt}` in Julia, e.g. `nums = BigInt[1,2,3]`, I think you can just pass it as `Ptr{BigInt}` to a C function that takes an `mpz_t *`.

Oh, I see, this isn’t going to work because `BigInt` is a _mutable_ struct in Julia, so a `nums::Vector{BigInt}` is internally an array of pointers to Julia objects (`jl_value_t*`).

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 4:24pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/16 "2025-05-06T16:24:26Z")

</div>

Is there anything one can do about that?

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [May 6, 2025, 4:42pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/17 "2025-05-06T16:42:59Z")

</div>

Try treating `Vector{BigInt}` as an array of `mpz_t*`:

```julia
void foo(mpz_t **nums, size_t len) {
    for (size_t i = 0; i < len; ++i)
        mpz_set_ui(nums[i], i);
}

```

and then call it as:

```julia
nums = BigInt[17, 23, 51]
@ccall mylibrary.foo(nums::Ptr{BigInt}, length(nums)::Csize_t)::Cvoid

```

---

<div class="post-metadata">

### Author: ![Questioner](https://avatars.discourse-cdn.com/v4/letter/q/e8c25b/32.png) [@Questioner](https://discourse.julialang.org/u/Questioner)
#### Post date: [May 6, 2025, 4:44pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/18 "2025-05-06T16:44:13Z")

</div>

I’ll give it a try; that should take about 10 min (since I’ve got problems with my Windows).

EDIT: It worked!

---

<div class="post-metadata">

### Author: ![danielwe](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/danielwe/32/35657_2.png) [@danielwe](https://discourse.julialang.org/u/danielwe)
#### Post date: [May 6, 2025, 7:04pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/19 "2025-05-06T19:04:46Z")

</div>

Just a note of caution: Different entries in an `Array{BigInt}` may actually be the same object. For example, when you do `zeros(BigInt, N)`, Julia only allocates a single `BigInt(0)` that’s referenced by every element of the array. This is safe as long as you stick to Julia’s public API, which only provides out-of-place operations, but if you’re using in-place operations on the C side (or you’re using non-public Julia functions), you need to be careful. Minimal example of what can go wrong:

```julia-repl
julia> xs = zeros(BigInt, 2)
2-element Vector{BigInt}:
 0
 0

julia> xs[1] === xs[2] # Uh oh!
true

julia> Base.GMP.MPZ.add_ui!(xs[1], BigInt(1)) # Increment the first element of xs
1

julia> xs # Oops...
2-element Vector{BigInt}:
 1
 1

```

---

<div class="post-metadata">

### Author: ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)
#### Post date: [May 6, 2025, 7:31pm UTC](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622/20 "2025-05-06T19:31:11Z")

</div>

> [@danielwe](#):
>
> Just a note of caution: Different entries in an `Array{BigInt}` may actually be the same object. For example, when you do `zeros(BigInt, N)`, Julia only allocates a single `BigInt(0)` that’s referenced by every element of the array.

If you call the `BigInt` constructor separately for each element that should guarantee distinct objects, e.g. `[BigInt(0) for _ = 1:10]` instead of `zeros(BigInt, 10)`.

[Next page](https://discourse.julialang.org/t/passing-a-bigint-mpz-t-for-gmp-array-to-c/123622.md?page=2)
