Passing GMP variables from C(++) to Julia

Hello there,

let me start by thanking the entirely altruistic help; in the long run, I hope to contribute to Julia myself.

Unfortunately, I’ve run into another issue: I’d like to convert a GNU MP type (such as mpz_t) into a Julia type (such as BigInteger), say when running a C code.

That is to say, I’d have an external (compiled) C program (or C++ program), which I’d like to call from Julia. I’d like this external program to pass a data type such as mpz_t to Julia, so that it is transformed into a BigInteger or the like.

Does anyone know whether this is possible? I’d be grateful for any help in this matter.

1 Like

I have some passing knowledge of the internals of Julia’s BigInt type; hence, I may be wrong. Julia wraps GMP, as seen in julia/base/gmp.jl, so interfacing with C/C++ code that uses GMP should work just fine. A BigInt stores a pointer to limbs that you would pass down to the C API, and it is also possible to initialise a BigInt from a C pointer, which a garbage collector can then track.

The biggest hurdle would be compiling the C/C++ code to use the same GMP library that Julia uses. If you manage to do that, the interfacing will work just fine. I have had a good experience pasting the whole julia/base/gmp.jl into Claude to write low-level methods, so I highly recommend trying that for your use case.

2 Likes

Thank you very much for your help, but what is “Claude”, apart from an impressionistic composer?

With Claude I meant large language model claude.ai

If some overhead is acceptable, a quick and dirty solution is passing strings between C++ and Julia. The strings can be parsed back to BigInt.

OK, I now managed to compile the code on Windows with the most recent GMP version; I know I was supposed to take the same version that Julia uses, but I do need to get it to work with a version discrepancy, because otherwise any new Julia version may destroy my code.

I have not yet managed to pass the data type, but I’m not sure whether thats due to the GMP versions being different or my insufficient understanding of passing types in C. For instance, what sort of pointer should I return from my C function? This last question seems to me of crucial importance.

I will now be trying to pass a BigInt from Julia to C by reference and have C modify it, because other methods have so far not produced any success.

That did not work, I’ve tried this C file

#include<gmp.h>

void setToTwo(mpz_t testInt) {
	mpz_init_set_ui(testInt, 2);
}

with this ccall

 @ccall "./gmptest.so".setToTwo(x::BigInt)::Cvoid

and the variable that I had passed and that I had initially set to 3 remained 3.

I did manage to get the BigInt into C though and then modify it there and return it as an int.

2 Likes

I’ve now managed to get it to work. The key was using pointers to pass by reference, as described here: Ccall: how to wrap call-by-reference C functions? - #2 by giordano

C code:

#include<gmp.h>

void setToTwo(mpz_t* testInt) {
	mpz_init_set_ui(*testInt, 2);
}

Julia code:

x = Ref{BigInt}(3)
@ccall "./gmptest.so".setToTwo(x::Ref{BigInt})::Cvoid

In this way, I managed to change x to 2.

2 Likes