diff --git a/examples/wasm-test/TestGeneral.gd b/examples/wasm-test/TestGeneral.gd
index 6da04f5..47ed39f 100644
--- a/examples/wasm-test/TestGeneral.gd
+++ b/examples/wasm-test/TestGeneral.gd
@@ -48,37 +48,6 @@ func test_invalid_binary():
 	expect_eq(error, ERR_INVALID_DATA)
 	expect_error("Invalid binary")
 
-func test_imports():
-	var imports = dummy_imports(["import.test_import"])
-	load_wasm("import", imports)
-	expect_empty()
-
-func test_invalid_imports():
-	var wasm = Wasm.new()
-	var buffer = read_file("import")
-	var error = wasm.compile(buffer)
-	expect_eq(error, OK)
-	# Missing import
-	var imports = {}
-	error = wasm.instantiate(imports)
-	expect_eq(error, ERR_CANT_CREATE)
-	expect_error("Missing import function import.test_import")
-	# Invalid import
-	imports = { "functions": { "import.test_import": [] } }
-	error = wasm.instantiate(imports)
-	expect_eq(error, ERR_CANT_CREATE)
-	expect_error("Invalid import function import.test_import")
-	# Invalid import target
-	imports = { "functions": { "import.test_import": [0, "dummy"] } }
-	error = wasm.instantiate(imports)
-	expect_eq(error, ERR_CANT_CREATE)
-	expect_error("Invalid import target")
-	# Invalid import method
-	imports = { "functions": { "import.test_import": [self, 0] } }
-	error = wasm.instantiate(imports)
-	expect_eq(error, ERR_CANT_CREATE)
-	expect_error("Invalid import method")
-
 func test_function():
 	var wasm = load_wasm("simple")
 	var result = wasm.function("add", [1, 2])
@@ -99,18 +68,18 @@ func test_uninstantiated_function():
 	expect_eq(result, null)
 	expect_error("Not instantiated")
 
-func test_invalid_function_args():
+func test_invalid_function_arg_type():
 	var wasm = load_wasm("simple")
 	var result = wasm.function("add", [{}, 2])
 	expect_eq(result, null)
 	expect_error("Unsupported Godot variant type")
 	expect_error("Invalid argument type")
 
-func test_callback_function():
-	var imports = dummy_imports(["import.test_import"])
-	var wasm = load_wasm("import", imports)
-	wasm.function("callback", [])
-	expect_log("Dummy import 123")
+func test_invalid_function_arg_count():
+	var wasm = load_wasm("simple")
+	var result = wasm.function("add", [1])
+	expect_eq(result, null)
+	expect_error("Incorrect number of arguments supplied")
 
 func test_global():
 	var wasm = load_wasm("simple")
@@ -158,24 +127,3 @@ func test_inspect():
 		"memory": {}
 	}
 	expect_eq(inspect, expected)
-	# Import module post-instantiation
-	var imports = dummy_imports(["import.test_import"])
-	wasm = load_wasm("import", imports)
-	inspect = wasm.inspect()
-	expected = {
-		"import_functions": {
-			"import.test_import": [[TYPE_INT], []],
-		},
-		"export_globals": {},
-		"export_functions": {
-			"_initialize": [[], []],
-			"callback": [[], []],
-		},
-		"memory": {
-			"min": 0,
-			"max": PAGES_MAX,
-			"current": 0,
-		}
-	}
-	expect_eq(inspect, expected)
-	expect_empty()
diff --git a/examples/wasm-test/TestImports.gd b/examples/wasm-test/TestImports.gd
new file mode 100644
index 0000000..dd730e5
--- /dev/null
+++ b/examples/wasm-test/TestImports.gd
@@ -0,0 +1,81 @@
+extends GodotWasmTestSuite
+
+func test_imports():
+	var imports = { "functions": {
+		"import.import_int": dummy_import(),
+		"import.import_float": dummy_import(),
+	} }
+	load_wasm("import", imports)
+	expect_empty()
+
+func test_invalid_imports():
+	var wasm = Wasm.new()
+	var buffer = read_file("import")
+	var error = wasm.compile(buffer)
+	expect_eq(error, OK)
+	# Missing import
+	var imports = {}
+	error = wasm.instantiate(imports)
+	expect_eq(error, ERR_CANT_CREATE)
+	expect_error("Missing import function import.import_(int|float)")
+	# Invalid import
+	imports = { "functions": {
+		"import.import_int": [],
+		"import.import_float": dummy_import(),
+	} }
+	error = wasm.instantiate(imports)
+	expect_eq(error, ERR_CANT_CREATE)
+	expect_error("Invalid import function import.import_int")
+	# Invalid import target
+	imports = { "functions": {
+		"import.import_int": [0, "dummy"],
+		"import.import_float": dummy_import(),
+	} }
+	error = wasm.instantiate(imports)
+	expect_eq(error, ERR_CANT_CREATE)
+	expect_error("Invalid import target import.import_int")
+	# Invalid import method
+	imports = { "functions": {
+		"import.import_int": [self, 0],
+		"import.import_float": dummy_import(),
+	} }
+	error = wasm.instantiate(imports)
+	expect_eq(error, ERR_CANT_CREATE)
+	expect_error("Invalid import method import.import_int")
+
+func test_callback_function():
+	var imports = { "functions": {
+		"import.import_int": dummy_import(),
+		"import.import_float": dummy_import(),
+	} }
+	var wasm = load_wasm("import", imports)
+	wasm.function("callback", [])
+	expect_log("Dummy import -123")
+	expect_log("Dummy import -12.34")
+
+func test_inspect():
+	# Import module post-instantiation
+	var imports = { "functions": {
+		"import.import_int": dummy_import(),
+		"import.import_float": dummy_import(),
+	} }
+	var wasm = load_wasm("import", imports)
+	var inspect = wasm.inspect()
+	var expected = {
+		"import_functions": {
+			"import.import_float": [[TYPE_FLOAT], []],
+			"import.import_int": [[TYPE_INT], []],
+		},
+		"export_globals": {},
+		"export_functions": {
+			"_initialize": [[], []],
+			"callback": [[], []],
+		},
+		"memory": {
+			"min": 0,
+			"max": PAGES_MAX,
+			"current": 0,
+		}
+	}
+	expect_eq(inspect, expected)
+	expect_empty()
diff --git a/examples/wasm-test/TestInference.gd b/examples/wasm-test/TestInference.gd
new file mode 100644
index 0000000..2d828b2
--- /dev/null
+++ b/examples/wasm-test/TestInference.gd
@@ -0,0 +1,13 @@
+extends GodotWasmTestSuite
+
+func test_param_types():
+	var wasm = load_wasm("inference", { "functions": {
+		"inference.echo_i32": dummy_import(),
+		"inference.echo_i64": dummy_import(),
+		"inference.echo_f32": dummy_import(),
+		"inference.echo_f64": dummy_import(),
+	} })
+	expect_eq(wasm.function("add_i32", [3, -1]), 2)
+	expect_eq(wasm.function("add_i64", [3, -1]), 2)
+	expect_approx(wasm.function("add_f32", [3.5, -1.2]), 2.3)
+	expect_approx(wasm.function("add_f64", [3.5, -1.2]), 2.3)
diff --git a/examples/wasm-test/utils/GodotWasmTestSuite.gd b/examples/wasm-test/utils/GodotWasmTestSuite.gd
index daae570..8b3fd43 100644
--- a/examples/wasm-test/utils/GodotWasmTestSuite.gd
+++ b/examples/wasm-test/utils/GodotWasmTestSuite.gd
@@ -25,15 +25,13 @@ func read_file(f: String) -> PoolByteArray:
 	return file.get_buffer(file.get_len())
 
 # Dummy import to supply to Wasm modules
-static func dummy(a = "", b = "", c = "", d = ""):
+static func _dummy_import(a = "", b = "", c = "", d = ""):
 	var message = "Dummy import %s %s %s %s" % [a, b, c, d]
 	print(message.strip_edges())
+	return a
 
-func dummy_imports(functions: Array = []) -> Dictionary:
-	var imports = { "functions": {} }
-	for function in functions:
-		imports.functions[function] = [self, "dummy"]
-	return imports
+func dummy_import() -> Array:
+	return [self, "_dummy_import"]
 
 func make_bytes(data: Array):
 	return PoolByteArray(data)
diff --git a/examples/wasm-test/utils/TestSuite.gd b/examples/wasm-test/utils/TestSuite.gd
index 97f5073..040e180 100644
--- a/examples/wasm-test/utils/TestSuite.gd
+++ b/examples/wasm-test/utils/TestSuite.gd
@@ -6,6 +6,8 @@ signal test_error(message)
 signal test_pass(case)
 signal test_fail(case)
 
+const EPSILON = 0.00001 # See https://github.com/godotengine/godot/blob/master/core/math/math_defs.h
+
 var _log_file # Log file used to check for output and/or errors
 var _error: bool = false # If the current test case has failed
 
@@ -62,6 +64,9 @@ func expect_type(a, t):
 func expect_within(a, b, c):
 	if abs(a - b) > c: _fail("Expect within: %s != %s ± %s" % [a, b, c])
 
+func expect_approx(a, b):
+	expect_within(a, b, EPSILON)
+
 func expect_includes(o, v: String):
 	if o is Dictionary:
 		if !o.keys().has(v): _fail("Expect contains: %s ∉ %s" % [v, o.keys()])
diff --git a/examples/wasm-test/wasm/import.wasm b/examples/wasm-test/wasm/import.wasm
index 48a9fbb..3085526 100644
Binary files a/examples/wasm-test/wasm/import.wasm and b/examples/wasm-test/wasm/import.wasm differ
diff --git a/examples/wasm-test/wasm/inference.wasm b/examples/wasm-test/wasm/inference.wasm
new file mode 100644
index 0000000..f57c18d
Binary files /dev/null and b/examples/wasm-test/wasm/inference.wasm differ
diff --git a/examples/wasm-test/wasm/memory-import.wasm b/examples/wasm-test/wasm/memory-import.wasm
index 4e0512b..aaef2f3 100644
Binary files a/examples/wasm-test/wasm/memory-import.wasm and b/examples/wasm-test/wasm/memory-import.wasm differ
diff --git a/src/godot-wasm.cpp b/src/godot-wasm.cpp
index 4465ceb..afa610b 100644
--- a/src/godot-wasm.cpp
+++ b/src/godot-wasm.cpp
@@ -15,12 +15,22 @@ namespace godot {
     struct ContextFuncImport: public ContextExtern {
       Object* target; // The object from which to invoke callback method
       String method; // External name; doesn't necessarily match import name
-      ContextFuncImport(uint16_t i): ContextExtern(i) { }
+      std::vector<wasm_valkind_t> results; // Return types
+      ContextFuncImport(uint16_t i, const wasm_functype_t* func_type): ContextExtern(i) {
+        const wasm_valtype_vec_t* func_results = wasm_functype_results(func_type);
+        for (uint16_t i = 0; i < func_results->size; i++) results.push_back(wasm_valtype_kind(func_results->data[i]));
+      }
     };
 
     struct ContextFuncExport: public ContextExtern {
       size_t return_count; // Number of return values
-      ContextFuncExport(uint16_t i, size_t return_count): ContextExtern(i), return_count(return_count) { }
+      std::vector<wasm_valkind_t> params; // Param types
+      ContextFuncExport(uint16_t i, const wasm_functype_t* func_type): ContextExtern(i) {
+        const wasm_valtype_vec_t* func_params = wasm_functype_params(func_type);
+        const wasm_valtype_vec_t* func_results = wasm_functype_results(func_type);
+        for (uint16_t i = 0; i < func_params->size; i++) params.push_back(wasm_valtype_kind(func_params->data[i]));
+        return_count = func_results->size;
+      }
     };
 
     struct ContextMemory: public ContextExtern {
@@ -42,6 +52,14 @@ namespace godot {
       p = NULL;
     }
 
+    inline wasm_val_t error_value(const char* message) {
+      PRINT_ERROR(message);
+      wasm_val_t value;
+      value.kind = WASM_ANYREF;
+      value.of.ref = NULL;
+      return value;
+    }
+
     Variant decode_variant(wasm_val_t value) {
       switch (value.kind) {
         case WASM_I32: return Variant(value.of.i32);
@@ -52,23 +70,35 @@ namespace godot {
       }
     }
 
-    wasm_val_t encode_variant(Variant variant) {
+    wasm_val_t encode_variant(Variant variant, wasm_valkind_t kind) {
       wasm_val_t value;
+      value.kind = kind;
       switch (variant.get_type()) {
         case Variant::INT:
-          value.kind = WASM_I64;
-          value.of.i64 = (int64_t)variant;
-          break;
+          switch (kind) {
+            case WASM_I32:
+              value.of.i32 = (int32_t)variant;
+              return value;
+            case WASM_I64:
+              value.of.i64 = (int64_t)variant;
+              return value;
+            default:
+              return error_value("Invalid target type for integer variant");
+          }
         case Variant::FLOAT:
-          value.kind = WASM_F64;
-          value.of.f64 = (float64_t)variant;
-          break;
+          switch (kind) {
+            case WASM_F32:
+              value.of.f32 = (float32_t)variant;
+              return value;
+            case WASM_F64:
+              value.of.f64 = (float64_t)variant;
+              return value;
+            default:
+              return error_value("Invalid target type for float variant");
+          }
         default:
-          PRINT_ERROR("Unsupported Godot variant type");
-          value.kind = WASM_ANYREF;
-          value.of.ref = NULL;
+          return error_value("Unsupported Godot variant type");
       }
-      return value;
     }
 
     String decode_name(const wasm_name_t* name) {
@@ -83,18 +113,19 @@ namespace godot {
       return d.has(k) && d[k].get_type() == Variant::OBJECT ? Object::cast_to<T>(d[k]) : NULL;
     }
 
-    godot_error extract_results(Variant variant, wasm_val_vec_t* results) {
+    godot_error extract_results(Variant variant, const godot_wasm::ContextFuncImport* context, wasm_val_vec_t* results) {
+      FAIL_IF(results->size != context->results.size(), "Incompatible return value(s)", ERR_INVALID_DATA);
       if (results->size <= 0) return OK;
       if (variant.get_type() == Variant::ARRAY) {
         Array array = variant.operator Array();
         if ((size_t)array.size() != results->size) return ERR_PARAMETER_RANGE_ERROR;
         for (uint16_t i = 0; i < results->size; i++) {
-          results->data[i] = encode_variant(array[i]);
+          results->data[i] = encode_variant(array[i], context->results[i]);
           if (results->data[i].kind == WASM_ANYREF) return ERR_INVALID_DATA;
         }
         return OK;
       } else if (results->size == 1) {
-        results->data[0] = encode_variant(variant);
+        results->data[0] = encode_variant(variant, context->results[0]);
         return results->data[0].kind == WASM_ANYREF ? ERR_INVALID_DATA : OK;
       } else return ERR_INVALID_DATA;
     }
@@ -175,7 +206,7 @@ namespace godot {
       for (uint16_t i = 0; i < args->size; i++) params.push_back(decode_variant(args->data[i]));
       // TODO: Ensure target is valid and has method
       Variant variant = context->target->callv(context->method, params);
-      godot_error error = extract_results(variant, results);
+      godot_error error = extract_results(variant, context, results);
       if (error) FAIL("Extracting import function results failed", trap("Extracting import function results failed\0"));
       return NULL;
     }
@@ -302,8 +333,8 @@ namespace godot {
       }
       const Array& import = dict_safe_get(functions, it.first, Array());
       FAIL_IF(import.size() != 2, "Invalid import function " + it.first, ERR_CANT_CREATE);
-      FAIL_IF(import[0].get_type() != Variant::OBJECT, "Invalid import target", ERR_CANT_CREATE);
-      FAIL_IF(import[1].get_type() != Variant::STRING, "Invalid import method", ERR_CANT_CREATE);
+      FAIL_IF(import[0].get_type() != Variant::OBJECT, "Invalid import target " + it.first, ERR_CANT_CREATE);
+      FAIL_IF(import[1].get_type() != Variant::STRING, "Invalid import method " + it.first, ERR_CANT_CREATE);
       godot_wasm::ContextFuncImport* context = (godot_wasm::ContextFuncImport*)&it.second;
       context->target = import[0];
       context->method = import[1];
@@ -406,11 +437,14 @@ namespace godot {
     const wasm_func_t* func = wasm_extern_as_func(data);
     FAIL_IF(func == NULL, "Failed to retrieve function export " + name, NULL_VARIANT);
 
+    // Validate argument count
+    FAIL_IF(context.params.size() != args.size(), "Incorrect number of arguments supplied", NULL_VARIANT);
+
     // Construct args
     std::vector<wasm_val_t> args_vec;
     for (uint16_t i = 0; i < args.size(); i++) {
       Variant variant = args[i];
-      wasm_val_t value = encode_variant(variant);
+      wasm_val_t value = encode_variant(variant, context.params[i]);
       FAIL_IF(value.kind == WASM_ANYREF, "Invalid argument type", NULL_VARIANT);
       args_vec.push_back(value);
     }
@@ -441,10 +475,11 @@ namespace godot {
       const wasm_externkind_t kind = wasm_externtype_kind(type);
       const String key = decode_name(wasm_importtype_module(imports.data[i])) + "." + decode_name(wasm_importtype_name(imports.data[i]));
       switch (kind) {
-        case WASM_EXTERN_FUNC:
-          import_funcs.emplace(key, godot_wasm::ContextFuncImport(i));
+        case WASM_EXTERN_FUNC: {
+          const wasm_functype_t* func_type = wasm_externtype_as_functype((wasm_externtype_t*)type);
+          import_funcs.emplace(key, godot_wasm::ContextFuncImport(i, func_type));
           break;
-        case WASM_EXTERN_MEMORY:
+        } case WASM_EXTERN_MEMORY:
           memory_context = new godot_wasm::ContextMemory(i, true);
           break;
         default: FAIL("Import type not implemented", ERR_INVALID_DATA);
@@ -462,8 +497,7 @@ namespace godot {
       switch (kind) {
         case WASM_EXTERN_FUNC: {
           const wasm_functype_t* func_type = wasm_externtype_as_functype((wasm_externtype_t*)type);
-          const wasm_valtype_vec_t* func_results = wasm_functype_results(func_type);
-          export_funcs.emplace(key, godot_wasm::ContextFuncExport(i, func_results->size));
+          export_funcs.emplace(key, godot_wasm::ContextFuncExport(i, func_type));
           break;
         } case WASM_EXTERN_GLOBAL:
           export_globals.emplace(key, godot_wasm::ContextExtern(i));