Skip to content

Commit 166a22d

Browse files
committed
Implement py_call_function
1 parent 48251a5 commit 166a22d

File tree

3 files changed

+201
-0
lines changed

3 files changed

+201
-0
lines changed

lib/Inline/Python.pm6

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ sub py_unicode_to_char_star(OpaquePointer)
4343
sub py_string_to_buf(OpaquePointer, CArray[CArray[int8]])
4444
returns Int { ... }
4545
native(&py_string_to_buf);
46+
sub py_call_function(Str, Str, int, CArray[OpaquePointer])
47+
returns OpaquePointer { ... }
48+
native(&py_call_function);
4649

4750
method py_to_p6(OpaquePointer $value) {
4851
if py_int_check($value) {
@@ -65,6 +68,38 @@ method py_to_p6(OpaquePointer $value) {
6568
return Any;
6669
}
6770

71+
method !setup_arguments(@args) {
72+
# my $len = @args.elems;
73+
# my @svs := CArray[OpaquePointer].new();
74+
# loop (my Int $i = 0; $i < $len; $i = $i + 1) {
75+
# @svs[$i] = self.p6_to_py(@args[$i]);
76+
# }
77+
# return $len, @svs;
78+
return 0;
79+
}
80+
81+
method !unpack_return_values($av) {
82+
# my $av_len = py_av_top_index($av);
83+
#
84+
# if $av_len == -1 {
85+
# p5_sv_refcnt_dec($av);
86+
# return;
87+
# }
88+
#
89+
# if $av_len == 0 {
90+
# my $retval = self.p5_to_p6(p5_av_fetch($av, 0));
91+
# p5_sv_refcnt_dec($av);
92+
# return $retval;
93+
# }
94+
#
95+
# my @retvals;
96+
# loop (my int32 $i = 0; $i <= $av_len; $i = $i + 1) {
97+
# @retvals.push(self.p5_to_p6(p5_av_fetch($av, $i)));
98+
# }
99+
# p5_sv_refcnt_dec($av);
100+
# @retvals;
101+
}
102+
68103
multi method run($python, :$eval!) {
69104
my $res = py_eval($python, 0);
70105
self.py_to_p6($res);
@@ -75,6 +110,12 @@ multi method run($python, :$file) {
75110
self.py_to_p6($res);
76111
}
77112

113+
method call(Str $package, Str $function, *@args) {
114+
my $array = py_call_function($package, $function, |self!setup_arguments(@args));
115+
return Any;
116+
self!unpack_return_values($array);
117+
}
118+
78119
method BUILD {
79120
py_init_python();
80121
}

pyhelper.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,21 @@ Py_ssize_t py_string_to_buf(PyObject *obj, char **buf) {
7777
fprintf(stderr, "%i\n", length);
7878
return length;
7979
}
80+
81+
PyObject *py_call_function(char *pkg, char *name, int len, PyObject *args[]) {
82+
int i;
83+
PyObject * const mod = PyImport_AddModule(pkg);
84+
PyObject * const dict = PyModule_GetDict(mod);
85+
PyObject * const func = PyMapping_GetItemString(dict, name);
86+
PyObject *o = NULL;
87+
PyObject *py_retval = NULL;
88+
PyObject *tuple = NULL;
89+
90+
tuple = PyTuple_New(0);
91+
92+
py_retval = PyObject_CallObject(func, tuple);
93+
Py_DECREF(func);
94+
Py_DECREF(tuple);
95+
96+
return py_retval;
97+
}

t/call.t

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
#!/usr/bin/env perl6
2+
3+
use v6;
4+
use Inline::Python;
5+
6+
say "1..12";
7+
8+
my $py = Inline::Python.new();
9+
say $py.run('
10+
11+
def test():
12+
print "ok 1 - executing a parameterless function without return value";
13+
return;
14+
15+
def test_int_params(a, b):
16+
if a == 2 and b == 2:
17+
print "ok 2 - int params";
18+
else:
19+
print "not ok 2 - int params";
20+
return;
21+
22+
def test_str_params(a, b):
23+
if a == "Hello" and b == "Python":
24+
print "ok 3 - str params";
25+
else:
26+
print "not ok 3 - str params";
27+
return;
28+
29+
def test_int_retval():
30+
return 1;
31+
32+
def test_int_retvals():
33+
return 3, 1, 2;
34+
35+
def test_str_retval():
36+
return "Hello Perl 6!";
37+
38+
def test_mixed_retvals():
39+
return ("Hello", "Perl", 6);
40+
41+
def test_none(undef):
42+
return undef is None;
43+
44+
import types
45+
def test_hash(h):
46+
return (
47+
isinstance(h, types.DictType)
48+
and len(h.keys()) == 2
49+
and "a" in h
50+
and "b" in h
51+
and h["a"] == 2
52+
and isinstance(h["b"], types.DictType)
53+
and isinstance(h["b"]["c"], types.ArrayType)
54+
and len(h["b"]["c"]) == 2
55+
and h["b"]["c"][0] == 4
56+
and h["b"]["c"][1] == 3
57+
)
58+
59+
def test_foo(foo):
60+
return foo.test();
61+
62+
class Foo:
63+
def __init__(self, val):
64+
self.val = val
65+
66+
def test(self):
67+
return self.val
68+
69+
def sum(a, b):
70+
return a + b
71+
');
72+
73+
$py.call('__main__', 'test');
74+
$py.call('__main__', 'test_int_params', 2, 1);
75+
$py.call('__main__', 'test_str_params', 'Hello', 'Perl 5');
76+
if ($py.call('__main__', 'test_int_retval') == 1) {
77+
say "ok 4 - return one int";
78+
}
79+
else {
80+
say "not ok 4 - return one int";
81+
}
82+
my @retvals = $py.call('__main__', 'test_int_retvals');
83+
if (@retvals == 3 and @retvals[0] == 3 and @retvals[1] == 1 and @retvals[2] == 2) {
84+
say "ok 5 - return one int";
85+
}
86+
else {
87+
say "not ok 5 - return one int";
88+
say " got: {@retvals}";
89+
say " expected: 3, 1, 2";
90+
}
91+
if ($py.call('__main__', 'test_str_retval') eq 'Hello Perl 6!') {
92+
say "ok 6 - return one string";
93+
}
94+
else {
95+
say "not ok 6 - return one string";
96+
}
97+
@retvals = $py.call('__main__', 'test_mixed_retvals');
98+
if (@retvals == 3 and @retvals[0] eq 'Hello' and @retvals[1] eq 'Perl' and @retvals[2] == 6) {
99+
say "ok 7 - return mixed values";
100+
}
101+
else {
102+
say "not ok 7 - return mixed values";
103+
say " got: {@retvals}";
104+
say " expected: 'Hello', 'Perl', 6";
105+
}
106+
107+
if ($py.call('__main__', 'Foo::new', 'Foo', 1).test() == 1) {
108+
say "ok 8 - Perl 5 method call";
109+
}
110+
else {
111+
say "not ok 8 - Perl 5 method call";
112+
}
113+
114+
if ($py.call('__main__', 'Foo::new', 'Foo', 1).sum(3, 1) == 4) {
115+
say "ok 9 - Perl 5 method call with parameters";
116+
}
117+
else {
118+
say "not ok 9 - Perl 5 method call with parameters";
119+
}
120+
121+
if ($py.call('__main__', 'test_none', Any) == 1) {
122+
say "ok 10 - Any converted to undef";
123+
}
124+
else {
125+
say "not ok 10 - Any converted to undef";
126+
}
127+
128+
if ($py.call('__main__', 'test_hash', {a => 2, b => {c => [4, 3]}}) == 1) {
129+
say "ok 11 - Passing hashes to Perl 5";
130+
}
131+
else {
132+
say "not ok 11 - Passing hashes to Perl 5";
133+
}
134+
135+
if ($py.call('__main__', 'test_foo', $py.call('__main__', 'Foo', 6)) == 6) {
136+
say "ok 12 - Passing Perl 5 objects back from Perl 6";
137+
}
138+
else {
139+
say "not ok 12 - Passing Perl 5 objects back from Perl 6";
140+
}
141+
142+
# vim: ft=perl6

0 commit comments

Comments
 (0)