Skip to content

Commit

Permalink
CallArgs struct
Browse files Browse the repository at this point in the history
  • Loading branch information
gatesn committed Oct 30, 2023
1 parent a72e3ee commit 2e5967d
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 20 deletions.
8 changes: 4 additions & 4 deletions pydust/src/pytypes.zig
Original file line number Diff line number Diff line change
Expand Up @@ -272,9 +272,9 @@ fn Slots(comptime definition: type, comptime name: [:0]const u8) type {
const kwargs = if (pykwargs) |pk| py.PyDict.unchecked(.{ .py = pk }) else null;

const init_args = tramp.Trampoline(Args).unwrapCallArgs(args, kwargs) catch return -1;
defer funcs.deinitArgs(Args, init_args);
defer init_args.deinit();

tramp.coerceError(definition.__init__(self, init_args)) catch return -1;
tramp.coerceError(definition.__init__(self, init_args.argsStruct)) catch return -1;
} else if (sig.selfParam) |_| {
tramp.coerceError(definition.__init__(self)) catch return -1;
} else {
Expand Down Expand Up @@ -364,9 +364,9 @@ fn Slots(comptime definition: type, comptime name: [:0]const u8) type {

const self = tramp.Trampoline(sig.selfParam.?).unwrap(py.PyObject{ .py = pyself }) catch return null;
const call_args = tramp.Trampoline(sig.argsParam.?).unwrapCallArgs(args, kwargs) catch return null;
defer funcs.deinitArgs(sig.argsParam.?, call_args);
defer call_args.deinit();

const result = tramp.coerceError(definition.__call__(self, call_args)) catch return null;
const result = tramp.coerceError(definition.__call__(self, call_args.argsStruct)) catch return null;
return (py.createOwned(result) catch return null).py;
}
};
Expand Down
43 changes: 27 additions & 16 deletions pydust/src/trampoline.zig
Original file line number Diff line number Diff line change
Expand Up @@ -275,27 +275,38 @@ pub fn Trampoline(comptime T: type) type {

// Unwrap the call args into a Pydust argument struct, borrowing references to the Python objects
// but instantiating the args slice and kwargs map containers.
// The caller is responsible for invoking funcs.deinitArgs on the returned struct.
pub inline fn unwrapCallArgs(pyargs: ?py.PyTuple, pykwargs: ?py.PyDict) PyError!T {
var kwargs = py.Kwargs.init(py.allocator);
if (pykwargs) |kw| {
var iter = kw.itemsIterator();
while (iter.next()) |item| {
const key: []const u8 = try (try py.PyString.checked(item.k)).asSlice();
try kwargs.put(key, item.v);
// The caller is responsible for invoking deinit on the returned struct.
pub inline fn unwrapCallArgs(pyargs: ?py.PyTuple, pykwargs: ?py.PyDict) PyError!ZigCallArgs {
return ZigCallArgs.unwrap(pyargs, pykwargs);
}

const ZigCallArgs = struct {
argsStruct: T,

pub fn unwrap(pyargs: ?py.PyTuple, pykwargs: ?py.PyDict) PyError!T {
var kwargs = py.Kwargs.init(py.allocator);
if (pykwargs) |kw| {
var iter = kw.itemsIterator();
while (iter.next()) |item| {
const key: []const u8 = try (try py.PyString.checked(item.k)).asSlice();
try kwargs.put(key, item.v);
}
}
}

const args = try py.allocator.alloc(py.PyObject, if (pyargs) |a| a.length() else 0);
defer py.allocator.free(args);
if (pyargs) |a| {
for (0..a.length()) |i| {
args[i] = try a.getItem(py.PyObject, i);
const args = try py.allocator.alloc(py.PyObject, if (pyargs) |a| a.length() else 0);
if (pyargs) |a| {
for (0..a.length()) |i| {
args[i] = try a.getItem(py.PyObject, i);
}
}

return .{ .argsStruct = funcs.unwrapArgs(T, args, kwargs) };
}

return funcs.unwrapArgs(T, args, kwargs);
}
pub fn deinit(self: @This()) void {
funcs.deinitArgs(self.argsStruct);
}
};
};
}

Expand Down

0 comments on commit 2e5967d

Please sign in to comment.