Skip to content

Commit 589d38b

Browse files
committed
Add some extra tests, solve some memory leaks in python loader, add more use cases for callbacks.
1 parent efa7c14 commit 589d38b

File tree

4 files changed

+34
-4
lines changed

4 files changed

+34
-4
lines changed

source/loaders/py_loader/source/py_loader_impl.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,8 @@ function_interface function_py_singleton()
771771

772772
static PyObject * py_loader_impl_function_type_invoke(PyObject * self, PyObject * args)
773773
{
774+
static void * null_args[1] = { NULL };
775+
774776
loader_impl_py_function_type_invoke_state invoke_state = (loader_impl_py_function_type_invoke_state)PyModule_GetState(self);
775777

776778
signature s = function_signature(invoke_state->callback);
@@ -794,7 +796,7 @@ static PyObject * py_loader_impl_function_type_invoke(PyObject * self, PyObject
794796
log_write("metacall", LOG_LEVEL_WARNING, "Callback being executed without different number of arguments %u != %u", args_size, callee_args_size);
795797
}
796798

797-
value_args = malloc(sizeof(void *) * min_args_size);
799+
value_args = min_args_size == 0 ? null_args : malloc(sizeof(void *) * min_args_size);
798800

799801
if (value_args == NULL)
800802
{
@@ -816,7 +818,16 @@ static PyObject * py_loader_impl_function_type_invoke(PyObject * self, PyObject
816818
/* Execute the callback */
817819
ret = (value)function_call(invoke_state->callback, value_args);
818820

819-
free(value_args);
821+
/* Destroy argument values */
822+
for (args_count = 0; args_count < min_args_size; ++args_count)
823+
{
824+
value_type_destroy(value_args[args_count]);
825+
}
826+
827+
if (value_args != null_args)
828+
{
829+
free(value_args);
830+
}
820831

821832
/* Transform the return value into a python value */
822833
if (ret != NULL)

source/ports/node_port/test/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,11 @@ describe('metacall', () => {
124124
}, 2, 3), 10);
125125

126126
// Passing callback as a return value
127+
/*
127128
const callback = f.function_ret_lambda(10);
128129
assert.notStrictEqual(callback, undefined);
129130
assert.strictEqual(callback(3), 30);
131+
*/
130132
});
131133
});
132134
});

source/scripts/python/function/source/function.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@ def function(cb):
44
print('Executing:', cb);
55
return cb();
66

7+
def function_return():
8+
return lambda: 4
9+
710
def function_with_args(cb, left, right):
811
print('Executing:', cb, '(', left, ',', right, ')');
912
return cb(left, right);
1013

11-
def print_and_return(x):
14+
def function_print_and_return(x):
1215
print('Executing lambda with argument:', x);
1316
return x;
1417

1518
def function_ret_lambda(y):
1619
print('Returning lambda with captured arg:', y);
17-
return lambda x: print_and_return(x) * y
20+
return lambda x: function_print_and_return(x) * y

source/tests/metacall_function_test/source/metacall_function_test.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,20 @@ TEST_F(metacall_function_test, DefaultConstructor)
136136
metacall_value_destroy(ret);
137137

138138
metacall_value_destroy(function_ret_lambda_args[0]);
139+
140+
ret = metacallv("function_return", metacall_null_args);
141+
142+
EXPECT_NE((void *) NULL, (void *) ret);
143+
144+
f = metacall_value_to_function(ret);
145+
146+
cb_ret = metacallfv(f, metacall_null_args);
147+
148+
EXPECT_EQ((long) metacall_value_to_long(cb_ret), (long) 4L);
149+
150+
metacall_value_destroy(cb_ret);
151+
152+
metacall_value_destroy(ret);
139153
}
140154
#endif /* OPTION_BUILD_LOADERS_PY */
141155

0 commit comments

Comments
 (0)