Compile an extern method

Return true if the compilation was successful, false if a fall-back is needed

Property definitions

nitc :: abstract_compiler $ AMethPropdef :: compile_externmeth_to_c
	# Compile an extern method
	# Return `true` if the compilation was successful, `false` if a fall-back is needed
	fun compile_externmeth_to_c(v: AbstractCompilerVisitor, mpropdef: MMethodDef, arguments: Array[RuntimeVariable]): Bool
	do
		var externname
		var at = self.get_single_annotation("extern", v.compiler.modelbuilder)
		if at != null and at.n_args.length == 1 then
			externname = at.arg_as_string(v.compiler.modelbuilder)
			if externname == null then return false
		else
			return false
		end
		v.add_extern(mpropdef.mclassdef.mmodule)
		var res: nullable RuntimeVariable = null
		var ret = mpropdef.msignature.return_mtype
		if ret != null then
			ret = v.resolve_for(ret, arguments.first)
			res = v.new_var_extern(ret)
		end
		v.adapt_signature(mpropdef, arguments)
		v.unbox_signature_extern(mpropdef, arguments)

		if res == null then
			v.add("{externname}({arguments.join(", ")});")
		else
			v.add("{res} = {externname}({arguments.join(", ")});")
			res = v.box_extern(res, ret.as(not null))
			v.ret(res)
		end
		return true
	end
src/compiler/abstract_compiler.nit:3502,2--3532,4

nitc :: light $ AMethPropdef :: compile_externmeth_to_c
	redef fun compile_externmeth_to_c(v, mpropdef, arguments)
	do
		# if using the old native interface fallback on previous implementation
		if n_extern_code_block == null then return super

		if not accept_externmeth then return false

		var mmodule = mpropdef.mclassdef.mmodule
		mmodule.uses_ffi = true

		var mclass_type = mpropdef.mclassdef.bound_mtype

		# Outgoing code in compiler
		var externname = mpropdef.mproperty.build_cname(mpropdef.mclassdef.bound_mtype, mmodule, "___impl", long_signature)
		var recv_var: nullable RuntimeVariable = null
		var return_mtype = mpropdef.msignature.return_mtype
		if return_mtype != null then
			return_mtype = return_mtype.anchor_to(mmodule, mclass_type)
			recv_var = v.new_var(return_mtype)
		end

		v.adapt_signature(mpropdef, arguments)
		v.unbox_signature_extern(mpropdef, arguments)

		var arguments_for_c = new Array[String]
		for a in [0..arguments.length[ do
			var arg = arguments[a]
			var param_mtype: MType
			if a == 0 then
				param_mtype = mpropdef.mclassdef.mclass.mclass_type
			else param_mtype = mpropdef.msignature.mparameters[a-1].mtype

			param_mtype = param_mtype.anchor_to(mmodule, mclass_type)

			if param_mtype.is_cprimitive then
				arguments_for_c.add(arg.name)
			else
				v.add("struct nitni_instance* var_for_c_{a};")
				v.add("var_for_c_{a} = nit_alloc(sizeof(struct nitni_instance));")
				v.add("var_for_c_{a}->value = {arg.name};")
				arguments_for_c.add("var_for_c_{a}")
			end
		end

		if recv_var == null then
			v.add("{externname}({arguments_for_c.join(", ")});")
		else
			assert return_mtype != null
			if return_mtype.is_cprimitive then
				v.add("{recv_var} = {externname}({arguments_for_c.join(", ")});")
			else
				v.add("struct nitni_instance* ret_var;")
				v.add("ret_var = {externname}({arguments_for_c.join(", ")});")
				v.add("{recv_var} = ret_var->value;")
			end
			recv_var = v.box_extern(recv_var, return_mtype)
			v.ret(recv_var)
		end

		compile_ffi_support_to_c(v)
		return true
	end
src/compiler/compiler_ffi/light.nit:107,2--168,4