The documentation is correct. And these macros exist for different
purposes, which is why they are defined differently. `JL_GC_PUSHARGS`
allocates gc-rooted space and stores a reference to it in the first
argument. `JL_GC_PUSH` does not allocate space, it instead takes the
address(es) of existing variables and uses them as slots for the garbage
collector's reachability analysis.

On Fri, Mar 27, 2015 at 4:12 PM Philip Roth <[email protected]> wrote:

>
> I'm embedding calls to Julia code within other languages, and have noticed
> what I think is an inconsistency in the implementation of the JL_GC_PUSH*
> macros.  With the JL_GC_PUSH1, JL_GC_PUSH2, etc. macros, the documentation
> on embedding shows to pass the *address* of the jl_value_t pointer
> variable to the macro, e.g.:
>
> jl_value_t* jret = NULL;
> JL_GC_PUSH1( &jret );
>
> However, if using JL_GC_PUSHARGS, the documentation says to just store the
> jl_value_t pointer value itself, e.g.:
>
> jl_value_t* jret = NULL;
> jl_value_t** gcargs;
> JL_GC_PUSHARGS(gcargs, 1);
> gcargs[0] = jret;
>
> I've verified using a debugger that the JL_GC_PUSH1 case stores the
> address of the pointer variable in the GC stack frame, whereas
> JL_GC_PUSHARGS stores the pointer variable's value itself.
>
> I tried changing my use of JL_GC_PUSHARGS so that it will accept the
> address of the jl_value_t pointer variable (made gcargs a jl_value_t*** and
> set gcargs[0] to &jret), but the implementation assumes that gcargs is a
> jl_value_t** and so it won't compile.  Conversely, I tried passing just
> jret to the JL_GC_PUSH1 macro.  It compiles, but the program SEGVs if I
> force a garbage collection after pushing the value.  Based on this, I think
> the JL_GC_PUSHARGS macro implementation is incorrect.
>
> So: is this operator error?  Or a bug in the implementation/documentation?
>
>
>

Reply via email to