gperl-i11n-invoke-c.c 20.3 KB
Newer Older
1 2
/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */

3
static void _prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
4 5 6 7 8 9
                                        GICallableInfo *info,
                                        IV items,
                                        UV internal_stack_offset,
                                        const gchar *package,
                                        const gchar *namespace,
                                        const gchar *function);
10 11
static void _clear_c_invocation_info (GPerlI11nCInvocationInfo *iinfo);
static void _check_n_args (GPerlI11nCInvocationInfo *iinfo);
12
static void _handle_automatic_arg (guint pos,
13 14
                                   GIArgInfo * arg_info,
                                   GITypeInfo * arg_type,
15
                                   GIArgument * arg,
16
                                   GPerlI11nCInvocationInfo * invocation_info);
17
static gpointer _allocate_out_mem (GITypeInfo *arg_type);
18

19
static void
20 21 22 23 24 25 26
invoke_c_code (GICallableInfo *info,
               gpointer func_pointer,
               SV **sp, I32 ax, SV **mark, I32 items, /* these correspond to dXSARGS */
               UV internal_stack_offset,
               const gchar *package,
               const gchar *namespace,
               const gchar *function)
27 28 29 30
{
	ffi_cif cif;
	gpointer instance = NULL;
	guint i;
31
	GPerlI11nCInvocationInfo iinfo;
32
	guint n_return_values;
33 34 35 36
#if GI_CHECK_VERSION (1, 32, 0)
	GIFFIReturnValue ffi_return_value;
#endif
	gpointer return_value_p;
37 38 39 40 41 42
	GIArgument return_value;
	GError * local_error = NULL;
	gpointer local_error_address = &local_error;

	PERL_UNUSED_VAR (mark);

43 44
	_prepare_c_invocation_info (&iinfo, info, items, internal_stack_offset,
	                            package, namespace, function);
45

46
	_check_n_args (&iinfo);
47 48

	if (iinfo.is_method) {
49
		instance = instance_sv_to_pointer (info, ST (0 + iinfo.stack_offset), &iinfo.base);
50
		iinfo.arg_types_ffi[0] = &ffi_type_pointer;
51 52 53
		iinfo.args[0] = &instance;
	}

54 55 56 57
	/*
	 * --- handle arguments -----------------------------------------------
	 */

58
	for (i = 0 ; i < iinfo.base.n_args ; i++) {
59 60 61
		GIArgInfo * arg_info;
		GITypeInfo * arg_type;
		GITransfer transfer;
62
		gboolean may_be_null = FALSE, is_skipped = FALSE;
63 64 65
		gint perl_stack_pos, ffi_stack_pos;
		SV *current_sv;

66 67
		arg_info = &(iinfo.base.arg_infos[i]);
		arg_type = &(iinfo.base.arg_types[i]);
68 69
		transfer = g_arg_info_get_ownership_transfer (arg_info);
		may_be_null = g_arg_info_may_be_null (arg_info);
70 71 72
#if GI_CHECK_VERSION (1, 29, 0)
		is_skipped = g_arg_info_is_skip (arg_info);
#endif
73 74 75 76
		perl_stack_pos = (gint) i
		               + (gint) iinfo.constructor_offset
		               + (gint) iinfo.method_offset
		               + (gint) iinfo.stack_offset
77
		               + iinfo.dynamic_stack_offset;
78 79 80
		ffi_stack_pos = (gint) i
		              + (gint) iinfo.method_offset;
		g_assert (perl_stack_pos >= 0 && ffi_stack_pos >= 0);
81 82 83 84 85 86

		/* FIXME: Is this right?  I'm confused about the relation of
		 * the numbers in g_callable_info_get_arg and
		 * g_arg_info_get_closure and g_arg_info_get_destroy.  We used
		 * to add method_offset, but that stopped being correct at some
		 * point. */
87
		iinfo.base.current_pos = i; /* + method_offset; */
88

89
		dwarn ("arg %d: tag = %d (%s), is_pointer = %d, is_automatic = %d\n",
90 91 92 93 94 95
		       i,
		       g_type_info_get_tag (arg_type),
		       g_type_tag_to_string (g_type_info_get_tag (arg_type)),
		       g_type_info_is_pointer (arg_type),
		       iinfo.is_automatic_arg[i]);

96 97
		/* Use undef for missing args (due to the checks above, these
		 * must be nullable). */
98 99 100 101 102 103
		current_sv = perl_stack_pos < items ? ST (perl_stack_pos) : &PL_sv_undef;

		switch (g_arg_info_get_direction (arg_info)) {
		    case GI_DIRECTION_IN:
			if (iinfo.is_automatic_arg[i]) {
				iinfo.dynamic_stack_offset--;
104
			} else if (is_skipped) {
105 106 107 108
				iinfo.dynamic_stack_offset--;
			} else {
				sv_to_arg (current_sv,
				           &iinfo.in_args[i], arg_info, arg_type,
109
				           transfer, may_be_null, &iinfo.base);
110
			}
111
			iinfo.arg_types_ffi[ffi_stack_pos] =
112 113 114 115 116 117
				g_type_info_get_ffi_type (arg_type);
			iinfo.args[ffi_stack_pos] = &iinfo.in_args[i];
			break;

		    case GI_DIRECTION_OUT:
			if (g_arg_info_is_caller_allocates (arg_info)) {
118
				iinfo.base.aux_args[i].v_pointer =
119
					_allocate_out_mem (arg_type);
120 121
				iinfo.out_args[i].v_pointer = &iinfo.base.aux_args[i];
				iinfo.args[ffi_stack_pos] = &iinfo.base.aux_args[i];
122
			} else {
123
				iinfo.out_args[i].v_pointer = &iinfo.base.aux_args[i];
124 125
				iinfo.args[ffi_stack_pos] = &iinfo.out_args[i];
			}
126
			iinfo.arg_types_ffi[ffi_stack_pos] = &ffi_type_pointer;
127 128 129 130 131 132 133 134
			/* Adjust the dynamic stack offset so that this out
			 * argument doesn't inadvertedly eat up an in argument. */
			iinfo.dynamic_stack_offset--;
			break;

		    case GI_DIRECTION_INOUT:
			iinfo.in_args[i].v_pointer =
				iinfo.out_args[i].v_pointer =
135
					&iinfo.base.aux_args[i];
136 137
			if (iinfo.is_automatic_arg[i]) {
				iinfo.dynamic_stack_offset--;
138
			} else if (is_skipped) {
139 140 141 142 143 144 145
				iinfo.dynamic_stack_offset--;
			} else {
				/* We pass iinfo.in_args[i].v_pointer here,
				 * not &iinfo.in_args[i], so that the value
				 * pointed to is filled from the SV. */
				sv_to_arg (current_sv,
				           iinfo.in_args[i].v_pointer, arg_info, arg_type,
146
				           transfer, may_be_null, &iinfo.base);
147
			}
148
			iinfo.arg_types_ffi[ffi_stack_pos] = &ffi_type_pointer;
149 150 151 152 153 154
			iinfo.args[ffi_stack_pos] = &iinfo.in_args[i];
			break;
		}
	}

	/* do another pass to handle automatic args */
155
	for (i = 0 ; i < iinfo.base.n_args ; i++) {
156
		GIArgInfo * arg_info;
157
		GITypeInfo * arg_type;
158 159
		if (!iinfo.is_automatic_arg[i])
			continue;
160 161
		arg_info = &(iinfo.base.arg_infos[i]);
		arg_type = &(iinfo.base.arg_types[i]);
162 163
		switch (g_arg_info_get_direction (arg_info)) {
		    case GI_DIRECTION_IN:
164
			_handle_automatic_arg (i, arg_info, arg_type, &iinfo.in_args[i], &iinfo);
165 166
			break;
		    case GI_DIRECTION_INOUT:
167
			_handle_automatic_arg (i, arg_info, arg_type, &iinfo.base.aux_args[i], &iinfo);
168 169 170 171 172 173 174 175 176
			break;
		    case GI_DIRECTION_OUT:
			/* handled later */
			break;
		}
	}

	if (iinfo.throws) {
		iinfo.args[iinfo.n_invoke_args - 1] = &local_error_address;
177
		iinfo.arg_types_ffi[iinfo.n_invoke_args - 1] = &ffi_type_pointer;
178 179
	}

180 181 182 183
	/*
	 * --- prepare & call -------------------------------------------------
	 */

184 185
	/* prepare and call the function */
	if (FFI_OK != ffi_prep_cif (&cif, FFI_DEFAULT_ABI, iinfo.n_invoke_args,
186
	                            iinfo.base.return_type_ffi, iinfo.arg_types_ffi))
187
	{
188
		_clear_c_invocation_info (&iinfo);
189 190 191
		ccroak ("Could not prepare a call interface");
	}

192 193 194 195 196 197
#if GI_CHECK_VERSION (1, 32, 0)
	return_value_p = &ffi_return_value;
#else
	return_value_p = &return_value;
#endif

198 199 200 201
	/* Wrap the call in PUTBACK/SPAGAIN because the C function might end up
	 * calling Perl code (via a vfunc), which might reallocate the stack
	 * and hence invalidate 'sp'. */
	PUTBACK;
202
	ffi_call (&cif, func_pointer, return_value_p, iinfo.args);
203
	SPAGAIN;
204

205
	/* free call-scoped data */
206
	invoke_free_after_call_handlers (&iinfo.base);
207 208

	if (local_error) {
209
		_clear_c_invocation_info (&iinfo);
210 211 212 213
		gperl_croak_gerror (NULL, local_error);
	}

	/*
214
	 * --- handle return values -------------------------------------------
215
	 */
216 217 218 219

#if GI_CHECK_VERSION (1, 32, 0)
	/* libffi has special semantics for return value storage; see `man
	 * ffi_call`.  We use gobject-introspection's extraction helper. */
220
	gi_type_info_extract_ffi_return_value (&iinfo.base.return_type_info,
221 222 223 224
	                                       &ffi_return_value,
	                                       &return_value);
#endif

225 226 227
	n_return_values = 0;

	/* place return value and output args on the stack */
228
	if (iinfo.base.has_return_value
229 230 231 232 233
#if GI_CHECK_VERSION (1, 29, 0)
	    && !g_callable_info_skip_return ((GICallableInfo *) info)
#endif
	   )
	{
234
		SV *value;
235
		dwarn ("return value: type = %p\n", &iinfo.base.return_type_info);
236
		value = SAVED_STACK_SV (arg_to_sv (&return_value,
237
		                                   &iinfo.base.return_type_info,
238 239
		                                   iinfo.base.return_type_transfer,
		                                   &iinfo.base));
240 241 242 243 244 245 246
		if (value) {
			XPUSHs (sv_2mortal (value));
			n_return_values++;
		}
	}

	/* out args */
247
	for (i = 0 ; i < iinfo.base.n_args ; i++) {
248 249 250
		GIArgInfo * arg_info;
		if (iinfo.is_automatic_arg[i])
			continue;
251
		arg_info = &(iinfo.base.arg_infos[i]);
252 253 254 255 256 257 258 259 260 261 262
#if GI_CHECK_VERSION (1, 29, 0)
		if (g_arg_info_is_skip (arg_info)) {
			continue;
		}
#endif
		switch (g_arg_info_get_direction (arg_info)) {
		    case GI_DIRECTION_OUT:
		    case GI_DIRECTION_INOUT:
		    {
			GITransfer transfer;
			SV *sv;
263
			dwarn ("out/inout arg at pos %d\n", i);
264 265 266 267
			/* If we allocated the memory ourselves, we always own it. */
			transfer = g_arg_info_is_caller_allocates (arg_info)
			         ? GI_TRANSFER_CONTAINER
			         : g_arg_info_get_ownership_transfer (arg_info);
268
			sv = SAVED_STACK_SV (arg_to_sv (iinfo.out_args[i].v_pointer,
269
			                                &(iinfo.base.arg_types[i]),
270
			                                transfer,
271
			                                &iinfo.base));
272 273 274 275 276 277 278 279 280 281 282 283
			if (sv) {
				XPUSHs (sv_2mortal (sv));
				n_return_values++;
			}
			break;
		    }

		    default:
			break;
		}
	}

284
	_clear_c_invocation_info (&iinfo);
285

286
	dwarn ("n_return_values = %d\n", n_return_values);
287 288 289

	PUTBACK;
}
290

291 292
/* ------------------------------------------------------------------------- */

293
static void
294
_prepare_c_invocation_info (GPerlI11nCInvocationInfo *iinfo,
295 296 297 298 299 300 301 302 303
                            GICallableInfo *info,
                            IV items,
                            UV internal_stack_offset,
                            const gchar *package,
                            const gchar *namespace,
                            const gchar *function)
{
	guint i;

304 305
	prepare_invocation_info ((GPerlI11nInvocationInfo *) iinfo, info);

306
	dwarn ("%s::%s::%s => %s\n",
307
	       package, namespace, function,
308
	       g_base_info_get_name (info));
309 310 311 312 313

	iinfo->target_package = package;
	iinfo->target_namespace = namespace;
	iinfo->target_function = function;

314 315 316
	iinfo->stack_offset = (guint) internal_stack_offset;
	g_assert (items >= iinfo->stack_offset);
	iinfo->n_given_args = ((guint) items) - iinfo->stack_offset;
317
	iinfo->n_invoke_args = iinfo->base.n_args;
318 319

	iinfo->is_constructor = FALSE;
320
	if (iinfo->base.is_function) {
321 322 323 324 325 326
		iinfo->is_constructor =
			g_function_info_get_flags (info) & GI_FUNCTION_IS_CONSTRUCTOR;
	}

	/* FIXME: can a vfunc not throw? */
	iinfo->throws = FALSE;
327
	if (iinfo->base.is_function) {
328 329 330 331
		iinfo->throws =
			g_function_info_get_flags (info) & GI_FUNCTION_THROWS;
	}
	if (iinfo->throws) {
332
		/* Add one for the implicit GError arg. */
333 334 335
		iinfo->n_invoke_args++;
	}

336
	if (iinfo->base.is_vfunc) {
337
		iinfo->is_method = TRUE;
338
	} else if (iinfo->base.is_callback) {
339 340 341 342 343 344 345
		iinfo->is_method = FALSE;
	} else {
		iinfo->is_method =
			(g_function_info_get_flags (info) & GI_FUNCTION_IS_METHOD)
			&& !iinfo->is_constructor;
	}
	if (iinfo->is_method) {
346
		/* Add one for the implicit invocant arg. */
347 348 349
		iinfo->n_invoke_args++;
	}

350 351 352 353 354 355 356 357 358 359
	dwarn ("  args = %u, given = %u, invoke = %u\n",
	       iinfo->base.n_args,
	       iinfo->n_given_args,
	       iinfo->n_invoke_args);

	dwarn ("  symbol = %s\n",
	       iinfo->base.is_vfunc ? g_base_info_get_name (info) : g_function_info_get_symbol (info));

	dwarn ("  is_constructor = %d, is_method = %d, throws = %d\n",
	       iinfo->is_constructor, iinfo->is_method, iinfo->throws);
360 361 362 363 364

	/* allocate enough space for all args in both the out and in lists.
	 * we'll only use as much as we need.  since function argument lists
	 * are typically small, this shouldn't be a big problem. */
	if (iinfo->n_invoke_args) {
365
		guint n = iinfo->n_invoke_args;
366 367
		iinfo->in_args = gperl_alloc_temp (sizeof (GIArgument) * n);
		iinfo->out_args = gperl_alloc_temp (sizeof (GIArgument) * n);
368
		iinfo->arg_types_ffi = gperl_alloc_temp (sizeof (ffi_type *) * n);
369 370 371 372
		iinfo->args = gperl_alloc_temp (sizeof (gpointer) * n);
		iinfo->is_automatic_arg = gperl_alloc_temp (sizeof (gboolean) * n);
	}

373 374 375 376
	/* If we call a constructor, we skip the initial package name resulting
	 * from the "Package->new" syntax.  If we call a method, we handle the
	 * invocant separately. */
	iinfo->constructor_offset = iinfo->is_constructor ? 1 : 0;
377 378 379 380 381
	iinfo->method_offset = iinfo->is_method ? 1 : 0;
	iinfo->dynamic_stack_offset = 0;

	/* Make a first pass to mark args that are filled in automatically, and
	 * thus have no counterpart on the Perl side. */
382
	for (i = 0 ; i < iinfo->base.n_args ; i++) {
383 384
		GIArgInfo * arg_info = &(iinfo->base.arg_infos[i]);
		GITypeInfo * arg_type = &(iinfo->base.arg_types[i]);
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
		GITypeTag arg_tag = g_type_info_get_tag (arg_type);

		if (arg_tag == GI_TYPE_TAG_ARRAY) {
			gint pos = g_type_info_get_array_length (arg_type);
			if (pos >= 0) {
				dwarn ("  pos %d is automatic (array length)\n", pos);
				iinfo->is_automatic_arg[pos] = TRUE;
			}
		}

		else if (arg_tag == GI_TYPE_TAG_INTERFACE) {
			GIBaseInfo * interface = g_type_info_get_interface (arg_type);
			GIInfoType info_type = g_base_info_get_type (interface);
			if (info_type == GI_INFO_TYPE_CALLBACK) {
				gint pos = g_arg_info_get_destroy (arg_info);
				if (pos >= 0) {
					dwarn ("  pos %d is automatic (callback destroy notify)\n", pos);
					iinfo->is_automatic_arg[pos] = TRUE;
				}
			}
			g_base_info_unref ((GIBaseInfo *) interface);
		}
	}

	/* Make another pass to count the expected args. */
410
	iinfo->n_expected_args = iinfo->constructor_offset + iinfo->method_offset;
411
	iinfo->n_nullable_args = 0;
412
	for (i = 0 ; i < iinfo->base.n_args ; i++) {
413 414
		GIArgInfo * arg_info = &(iinfo->base.arg_infos[i]);
		GITypeInfo * arg_type = &(iinfo->base.arg_types[i]);
415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431
		GITypeTag arg_tag = g_type_info_get_tag (arg_type);
		gboolean is_out = GI_DIRECTION_OUT == g_arg_info_get_direction (arg_info);
		gboolean is_automatic = iinfo->is_automatic_arg[i];
		gboolean is_skipped = FALSE;
#if GI_CHECK_VERSION (1, 29, 0)
		is_skipped = g_arg_info_is_skip (arg_info);
#endif

		if (!is_out && !is_automatic && !is_skipped)
			iinfo->n_expected_args++;
		/* Callback user data may always be NULL. */
		if (g_arg_info_may_be_null (arg_info) || arg_tag == GI_TYPE_TAG_VOID)
			iinfo->n_nullable_args++;
	}

	/* If the return value is an array which comes with an outbound length
	 * arg, then mark that length arg as automatic, too. */
432 433
	if (g_type_info_get_tag (&iinfo->base.return_type_info) == GI_TYPE_TAG_ARRAY) {
		gint pos = g_type_info_get_array_length (&iinfo->base.return_type_info);
434
		if (pos >= 0) {
435
			GIArgInfo * arg_info = &(iinfo->base.arg_infos[pos]);
436 437 438 439 440 441 442 443 444
			if (GI_DIRECTION_OUT == g_arg_info_get_direction (arg_info)) {
				dwarn ("  pos %d is automatic (array length)\n", pos);
				iinfo->is_automatic_arg[pos] = TRUE;
			}
		}
	}

	/* We need to undo the special handling that GInitiallyUnowned
	 * descendants receive from gobject-introspection: values of this type
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462
	 * are always marked transfer=none, even for constructors.
	 *
	 * FIXME: This is not correct for GtkWindow and its descendants, as
	 * gtk+ keeps an internal reference to each window.  Hence,
	 * constructors like gtk_window_new return a non-floating object and do
	 * not pass ownership of a reference on to us.  But the sink func
	 * currently registered for GInitiallyUnowned (sink_initially_unowned
	 * in GObject.xs in Glib) is actually inadvertently conforming to this
	 * requirement.  It runs ref_sink+unref regardless of whether the
	 * object is floating or not.  So, in the non-floating window case, it
	 * does nothing, resulting in an extra reference taken, despite the
	 * request to transfer ownership.
	 *
	 * If we ever encounter a constructor of a GInitiallyUnowned descendant
	 * that returns a non-floating object and passes ownership of a
	 * reference on to us, or a constructor of a GInitiallyUnowned
	 * descendant that returns a floating object but passes no reference on
	 * to us, then we need to revisit this. */
463
	if (iinfo->is_constructor &&
464
	    g_type_info_get_tag (&iinfo->base.return_type_info) == GI_TYPE_TAG_INTERFACE)
465
	{
466
		GIBaseInfo * interface = g_type_info_get_interface (&iinfo->base.return_type_info);
467 468 469 470
		if (GI_IS_REGISTERED_TYPE_INFO (interface) &&
		    g_type_is_a (get_gtype (interface),
		                 G_TYPE_INITIALLY_UNOWNED))
		{
471
			iinfo->base.return_type_transfer = GI_TRANSFER_EVERYTHING;
472 473 474 475 476 477
		}
		g_base_info_unref ((GIBaseInfo *) interface);
	}
}

static void
478
_clear_c_invocation_info (GPerlI11nCInvocationInfo *iinfo)
479
{
480
	clear_invocation_info ((GPerlI11nInvocationInfo *) iinfo);
481 482 483 484 485
}

/* ------------------------------------------------------------------------- */

static gchar *
486
_format_target (GPerlI11nCInvocationInfo *iinfo)
487 488 489 490 491 492 493 494 495 496 497 498 499
{
	gchar *caller = NULL;
	if (iinfo->target_package && iinfo->target_namespace && iinfo->target_function) {
		caller = g_strconcat (iinfo->target_package, "::",
		                      iinfo->target_namespace, "::",
		                      iinfo->target_function,
		                      NULL);
	} else if (iinfo->target_package && iinfo->target_function) {
		caller = g_strconcat (iinfo->target_package, "::",
		                      iinfo->target_function,
		                      NULL);
	} else {
		caller = g_strconcat ("Callable ",
500
		                      g_base_info_get_name (iinfo->base.interface),
501 502 503 504 505 506
		                      NULL);
	}
	return caller;
}

static void
507
_check_n_args (GPerlI11nCInvocationInfo *iinfo)
508 509 510 511 512 513 514 515
{
	if (iinfo->n_expected_args != iinfo->n_given_args) {
		/* Avoid the cost of formatting the target until we know we
		 * need it. */
		gchar *caller = NULL;
		if (iinfo->n_given_args < (iinfo->n_expected_args - iinfo->n_nullable_args)) {
			caller = _format_target (iinfo);
			ccroak ("%s: passed too few parameters "
516
			        "(expected %u, got %u)",
517 518 519 520
			        caller, iinfo->n_expected_args, iinfo->n_given_args);
		} else if (iinfo->n_given_args > iinfo->n_expected_args) {
			caller = _format_target (iinfo);
			cwarn ("*** %s: passed too many parameters "
521
			       "(expected %u, got %u); ignoring excess",
522 523 524 525 526 527 528 529 530 531 532
			       caller, iinfo->n_expected_args, iinfo->n_given_args);
		}
		if (caller)
			g_free (caller);
	}
}

/* ------------------------------------------------------------------------- */

static void
_handle_automatic_arg (guint pos,
533 534
                       GIArgInfo * arg_info,
                       GITypeInfo * arg_type,
535
                       GIArgument * arg,
536
                       GPerlI11nCInvocationInfo * invocation_info)
537 538 539 540
{
	GSList *l;

	/* array length */
541
	for (l = invocation_info->base.array_infos; l != NULL; l = l->next) {
542
		GPerlI11nArrayInfo *ainfo = l->data;
543
		if (((gint) pos) == ainfo->length_pos) {
544
			SV *conversion_sv;
545
			dwarn ("  setting automatic arg %d (array length) to %"G_GSIZE_FORMAT"\n",
546
			       pos, ainfo->length);
547 548 549 550
			conversion_sv = newSVuv (ainfo->length);
			sv_to_arg (conversion_sv, arg, arg_info, arg_type,
			           GI_TRANSFER_NOTHING, FALSE, NULL);
			SvREFCNT_dec (conversion_sv);
551 552 553 554 555
			return;
		}
	}

	/* callback destroy notify */
556
	for (l = invocation_info->base.callback_infos; l != NULL; l = l->next) {
557
		GPerlI11nPerlCallbackInfo *cinfo = l->data;
558
		if (((gint) pos) == cinfo->destroy_pos) {
559 560
			dwarn ("  setting automatic arg %d (destroy notify for calllback %p)\n",
			       pos, cinfo);
561 562 563 564 565
			/* If the code pointer is NULL, then the user actually
			 * specified undef for the callback or nothing at all,
			 * in which case we must not install our destroy notify
			 * handler. */
			arg->v_pointer = cinfo->code ? release_perl_callback : NULL;
566 567 568 569 570 571 572 573
			return;
		}
	}

	ccroak ("Could not handle automatic arg %d", pos);
}

static gpointer
574
_allocate_out_mem (GITypeInfo *arg_type)
575 576 577
{
	GIBaseInfo *interface_info;
	GIInfoType type;
578 579
	gboolean is_boxed = FALSE;
	GType gtype = G_TYPE_INVALID;
580 581 582 583

	interface_info = g_type_info_get_interface (arg_type);
	g_assert (interface_info);
	type = g_base_info_get_type (interface_info);
584 585 586 587
	if (GI_IS_REGISTERED_TYPE_INFO (interface_info)) {
		gtype = get_gtype (interface_info);
		is_boxed = g_type_is_a (gtype, G_TYPE_BOXED);
	}
588 589 590 591 592 593 594
	g_base_info_unref (interface_info);

	switch (type) {
	    case GI_INFO_TYPE_STRUCT:
	    {
		/* No plain g_struct_info_get_size (interface_info) here so
		 * that we get the GValue override. */
595 596 597 598 599 600 601 602 603 604 605 606 607 608
		gsize size;
		gpointer mem;
		size = size_of_interface (arg_type);
		mem = g_malloc0 (size);
		if (is_boxed) {
			/* For a boxed type, malloc() might not be the right
			 * allocator.  For example, GtkTreeIter uses GSlice.
			 * So use g_boxed_copy() to make a copy of the newly
			 * allocated block using the correct allocator. */
			gpointer real_mem = g_boxed_copy (gtype, mem);
			g_free (mem);
			mem = real_mem;
		}
		return mem;
609 610 611 612 613 614
	    }
	    default:
		g_assert_not_reached ();
		return NULL;
	}
}