diff --git a/gobject/valaccodeassignmentbinding.vala b/gobject/valaccodeassignmentbinding.vala
index 13a970e..00f6cb1 100644
--- a/gobject/valaccodeassignmentbinding.vala
+++ b/gobject/valaccodeassignmentbinding.vala
@@ -288,7 +288,7 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
 			var delegate_type = (DelegateType) assignment.left.value_type;
 			instance_delegate = delegate_type.delegate_symbol.has_target;
 		}
-		
+
 		if (unref_old || array || instance_delegate) {
 			var ccomma = new CCodeCommaExpression ();
 			
@@ -341,8 +341,27 @@ public class Vala.CCodeAssignmentBinding : CCodeExpressionBinding {
 		} else if (assignment.operator == AssignmentOperator.SHIFT_RIGHT) {
 			cop = CCodeAssignmentOperator.SHIFT_RIGHT;
 		}
+
+		if (assignment.left.value_type.data_type != null
+		    && assignment.left.value_type.data_type.get_type_id () == "G_TYPE_VALUE" 
+		    && assignment.right.value_type.data_type.get_set_value_function () != null) {
+			codegen.requires_value_init = true;
+
+			var ccall_init = new CCodeFunctionCall (new CCodeIdentifier ("VALA_VALUE_INIT"));
+			ccall_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) assignment.left.ccodenode));
+			ccall_init.add_argument (new CCodeConstant (assignment.right.value_type.data_type.get_type_id ()));
 	
-		codenode = new CCodeAssignment ((CCodeExpression) assignment.left.ccodenode, rhs, cop);
+			var ccall_set = new CCodeFunctionCall (new CCodeIdentifier (assignment.right.value_type.data_type.get_set_value_function ()));
+			ccall_set.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) assignment.left.ccodenode));
+			ccall_set.add_argument ((CCodeExpression) assignment.right.ccodenode);
+
+			var ccomma = new CCodeCommaExpression ();
+			ccomma.append_expression (ccall_init);
+			ccomma.append_expression (ccall_set);
+			codenode = ccomma; 
+		} else {
+			codenode = new CCodeAssignment ((CCodeExpression) assignment.left.ccodenode, rhs, cop);
+		}
 
 		if (unref_old && assignment.left.ccodenode is CCodeElementAccess) {
 			// ensure that index expression in element access doesn't get evaluated more than once
diff --git a/gobject/valaccodegenerator.vala b/gobject/valaccodegenerator.vala
index ecbaf1e..fc35889 100644
--- a/gobject/valaccodegenerator.vala
+++ b/gobject/valaccodegenerator.vala
@@ -106,6 +106,7 @@ public class Vala.CCodeGenerator : CodeGenerator {
 	public DataType double_type;
 	public TypeSymbol gtype_type;
 	public TypeSymbol gobject_type;
+	public DataType gvalue_type;
 	public ErrorType gerror_type;
 	public Class glist_type;
 	public Class gslist_type;
@@ -131,6 +132,7 @@ public class Vala.CCodeGenerator : CodeGenerator {
 	private bool requires_array_free;
 	public bool requires_array_move;
 	private bool requires_strcmp0;
+	public bool requires_value_init;
 	public bool dbus_glib_h_needed;
 
 	private Set<string> wrappers;
@@ -233,6 +235,7 @@ public class Vala.CCodeGenerator : CodeGenerator {
 
 		gtype_type = (TypeSymbol) glib_ns.scope.lookup ("Type");
 		gobject_type = (TypeSymbol) glib_ns.scope.lookup ("Object");
+		gvalue_type = new ValueType ((TypeSymbol) glib_ns.scope.lookup ("Value"));
 		gerror_type = new ErrorType (null, null);
 		glist_type = (Class) glib_ns.scope.lookup ("List");
 		gslist_type = (Class) glib_ns.scope.lookup ("SList");
@@ -3368,7 +3371,15 @@ public class Vala.CCodeGenerator : CodeGenerator {
 				Report.error (expr.source_reference, "Operation not supported for this type");
 				return;
 			}
-			expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
+			if (expr.inner.value_type.data_type != null
+			    && expr.inner.value_type.data_type.get_type_id () == "G_TYPE_VALUE"
+			    && expr.type_reference.data_type.get_get_value_function () != null) {
+				var ccall = new CCodeFunctionCall (new CCodeIdentifier (expr.type_reference.data_type.get_get_value_function ()));
+				ccall.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, (CCodeExpression) expr.inner.ccodenode));
+				expr.ccodenode = ccall;
+			} else {
+				expr.ccodenode = new CCodeCastExpression ((CCodeExpression) expr.inner.ccodenode, expr.type_reference.get_cname ());
+			}
 		}
 	}
 	
diff --git a/gobject/valaccodegeneratorsourcefile.vala b/gobject/valaccodegeneratorsourcefile.vala
index 4149d00..16caa40 100644
--- a/gobject/valaccodegeneratorsourcefile.vala
+++ b/gobject/valaccodegeneratorsourcefile.vala
@@ -287,7 +287,10 @@ public class Vala.CCodeGenerator {
 		if (requires_strcmp0) {
 			append_vala_strcmp0 ();
 		}
-		
+		if (requires_value_init) {
+			source_type_declaration.append (new CCodeMacroReplacement ("VALA_VALUE_INIT(v,t)", "(!G_IS_VALUE (v) ? g_value_init (v, t) : (G_VALUE_TYPE (v) != t ? (g_value_unset (v), g_value_init (v,t)) : NULL))"));
+		}
+
 		if (string_h_needed) {
 			source_include_directives.append (new CCodeIncludeDirective ("string.h"));
 		}
diff --git a/gobject/valaccodeinvocationexpressionbinding.vala b/gobject/valaccodeinvocationexpressionbinding.vala
index a133834..837f904 100644
--- a/gobject/valaccodeinvocationexpressionbinding.vala
+++ b/gobject/valaccodeinvocationexpressionbinding.vala
@@ -223,9 +223,24 @@ public class Vala.CCodeInvocationExpressionBinding : CCodeExpressionBinding {
 								// (tmp = expr, &tmp)
 								var ccomma = new CCodeCommaExpression ();
 
-								var temp_var = codegen.get_temp_variable (arg.value_type);
+								var temp_var = codegen.get_temp_variable (param.parameter_type); //arg.value_type);
 								codegen.temp_vars.insert (0, temp_var);
-								ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), cexpr));
+
+								//implicit conversion to GValue
+								if (param.parameter_type.get_type_id () == "G_TYPE_VALUE" && arg.value_type.data_type.get_set_value_function () != null) {
+									var ccall_init = new CCodeFunctionCall (new CCodeIdentifier ("VALA_VALUE_INIT"));
+									ccall_init.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name)));
+									ccall_init.add_argument (new CCodeConstant (arg.value_type.get_type_id ()));
+									ccomma.append_expression (ccall_init);
+
+									var ccall_set = new CCodeFunctionCall (new CCodeIdentifier (arg.value_type.data_type.get_set_value_function ()));
+									ccall_set.add_argument (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name)));
+									ccall_set.add_argument (cexpr);
+									ccomma.append_expression (ccall_set);
+								} else {
+									ccomma.append_expression (new CCodeAssignment (new CCodeIdentifier (temp_var.name), cexpr));
+								}
+
 								ccomma.append_expression (new CCodeUnaryExpression (CCodeUnaryOperator.ADDRESS_OF, new CCodeIdentifier (temp_var.name)));
 
 								cexpr = ccomma;
diff --git a/vala/valadatatype.vala b/vala/valadatatype.vala
index ff6f076..80910a3 100644
--- a/vala/valadatatype.vala
+++ b/vala/valadatatype.vala
@@ -354,6 +354,11 @@ public abstract class Vala.DataType : CodeNode {
 			return true;
 		}
 
+		if (target_type.get_type_id () == "G_TYPE_VALUE"
+		    && this.data_type.get_set_value_function () != null) {
+			return true;
+		}
+
 		return false;
 	}
 
