diff --git a/src/box/call.cc b/src/box/call.cc
index 3e07ac7dad02da71a71a279a534894d0ed7d51e8..c8fbf3d33c05c100722ef07a67859d4d37f13944 100644
--- a/src/box/call.cc
+++ b/src/box/call.cc
@@ -69,23 +69,22 @@ access_check_func(const char *name, uint32_t name_len)
 }
 
 static int
-func_call(struct func *func, struct call_request *request, struct obuf *out)
+box_c_call(struct func *func, struct call_request *request, struct obuf *out)
 {
 	assert(func != NULL && func->def->language == FUNC_LANGUAGE_C);
-	if (func->func == NULL)
-		func_load(func);
 
 	/* Create a call context */
 	struct port port;
 	port_create(&port);
 	auto port_guard = make_scoped_guard([&](){ port_destroy(&port); });
-	box_function_ctx_t ctx = { request, &port };
+	box_function_ctx_t ctx = { &port };
 
 	/* Clear all previous errors */
 	diag_clear(&fiber()->diag);
 	assert(!in_txn()); /* transaction is not started */
+
 	/* Call function from the shared library */
-	int rc = func->func(&ctx, request->args, request->args_end);
+	int rc = func_call(func, &ctx, request->args, request->args_end);
 	if (rc != 0) {
 		if (diag_last_error(&fiber()->diag) == NULL) {
 			/* Stored procedure forget to set diag  */
@@ -171,7 +170,7 @@ box_process_call(struct call_request *request, struct obuf *out)
 
 	int rc;
 	if (func && func->def->language == FUNC_LANGUAGE_C) {
-		rc = func_call(func, request, out);
+		rc = box_c_call(func, request, out);
 	} else {
 		rc = box_lua_call(request, out);
 	}
diff --git a/src/box/call.h b/src/box/call.h
index 826ca4d5fe22d1d4646822d693e2da0a2c5fa5f3..b44a696f1c1d235f219d4210b9ebfbdbfccb0278 100644
--- a/src/box/call.h
+++ b/src/box/call.h
@@ -36,7 +36,6 @@
 struct obuf;
 
 struct box_function_ctx {
-	struct call_request *request;
 	struct port *port;
 };
 
diff --git a/src/box/func.cc b/src/box/func.cc
index c37d9be47c860f36440d051bc2696ab017a44313..da456ab1bf3eccb800a3b786a5ba9e8424e03337 100644
--- a/src/box/func.cc
+++ b/src/box/func.cc
@@ -171,29 +171,50 @@ func_unload(struct func *func)
 	func->func = NULL;
 }
 
-void
+/**
+ * Resolve func->func (find the respective DLL and fetch the
+ * symbol from it).
+ */
+static int
 func_load(struct func *func)
 {
-	func_unload(func);
+	assert(func->func == NULL);
 
 	struct func_name name;
 	func_split_name(func->def->name, &name);
 
 	char path[PATH_MAX];
 	if (module_find(name.package, name.package_end, path, sizeof(path)))
-		diag_raise();
+		return -1;
 
 	func->dlhandle = dlopen(path, RTLD_NOW | RTLD_LOCAL);
 	if (func->dlhandle == NULL) {
 		int package_len = (int) (name.package_end - name.package_end);
-		tnt_raise(LoggedError, ER_LOAD_MODULE, package_len,
+		diag_set(ClientError, ER_LOAD_MODULE, package_len,
 			  name.package, dlerror());
+		diag_log();
+		return -1;
 	}
 	func->func = (box_function_f) dlsym(func->dlhandle, name.sym);
 	if (func->func == NULL) {
-		tnt_raise(LoggedError, ER_LOAD_FUNCTION, func->def->name,
+		diag_set(ClientError, ER_LOAD_FUNCTION, func->def->name,
 			  dlerror());
+		diag_log();
+		return -1;
 	}
+	return 0;
+}
+
+int
+func_call(struct func *func, box_function_ctx_t *ctx, const char *args,
+	  const char *args_end)
+{
+	if (func->func == NULL) {
+		if (func_load(func) != 0)
+			return -1;
+	}
+
+	return func->func(ctx, args, args_end);
 }
 
 void
diff --git a/src/box/func.h b/src/box/func.h
index c29b964ea528215f4d377640e6736b8ecd569ddf..d5a51a354b2f81afd79842e10dda4e88da411d97 100644
--- a/src/box/func.h
+++ b/src/box/func.h
@@ -74,11 +74,11 @@ void
 func_delete(struct func *func);
 
 /**
- * Resolve func->func (find the respective DLL and fetch the
- * symbol from it).
+ * Call stored C function using @a args.
  */
-void
-func_load(struct func *func);
+int
+func_call(struct func *func, box_function_ctx_t *ctx, const char *args,
+	  const char *args_end);
 
 #endif /* defined(__cplusplus) */