Skip to content

Commit

Permalink
SWIG bindings for user_cb_data in repo::DownloadCallbacks
Browse files Browse the repository at this point in the history
In the C++ API, the user can return a pointer (void *) to user data
in the `add_new_download` method of the `repo::DownlodCallbacks` class.
This pointer is then passed as an argument to `void * user_cb_data`
in other methods of the `repo::DownloadCallbacks` class.

There was a problem of how to use this mechanism in SWIG bindings.

I implemented and tested several solutions.
In the case of passing a pointer, there was a problem with the ownership
of the data the pointer points to. Users of Python and some other languages
are used to the gargabe collector and automatically holding ownership
of the passed data. While I've solved this for `user_cb_data`, passing another
void pointer will need to be solved (I'll do that later). And from there,
the ownership will be more complicated. We need the solution to work reliably
in Python, Ruby and Perl. And possibly be easy to use for other languages
in the future.

In the end, I chose the method of passing an integer instead of a pointer.
When passing an integer, there is no need to deal with who owns the number.
The integer is passed by value. And if the user needs to pass objects,
for example, he can create an array of objects and pass the index (integer)
to the array. The array also provides ownership of the objects.
  • Loading branch information
jrohel authored and m-blaha committed Nov 18, 2024
1 parent 9b3c009 commit 3b07d21
Showing 1 changed file with 33 additions and 0 deletions.
33 changes: 33 additions & 0 deletions bindings/libdnf5/repo.i
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,40 @@
%include "libdnf5/repo/config_repo.hpp"

%feature("director") DownloadCallbacks;

%typemap(directorin, noblock=1) void * user_cb_data {
$input = SWIG_From_int(static_cast<int>(reinterpret_cast<intptr_t>($1)));
}

%typemap(directorout, noblock=1) void * {
int swig_val;
int swig_res = SWIG_AsVal_int($1, &swig_val);
if (!SWIG_IsOK(swig_res)) {
Swig::DirectorTypeMismatchException::raise(SWIG_ErrorType(SWIG_ArgError(swig_res)), "in output value of type '""int""'");
}
$result = reinterpret_cast<void *>(swig_val);
}

%typemap(in, noblock=1) void * user_cb_data {
{
int swig_val;
int swig_res = SWIG_AsVal_int($input, &swig_val);
if (!SWIG_IsOK(swig_res)) {
Swig::DirectorTypeMismatchException::raise(SWIG_ErrorType(SWIG_ArgError(swig_res)), "in input value of type '""int""'");
}
$1 = reinterpret_cast<void *>(swig_val);
}
}

%typemap(out, noblock=1) void * {
$result = SWIG_From_int(static_cast<int>(reinterpret_cast<intptr_t>($1)));
}

%include "libdnf5/repo/download_callbacks.hpp"
%typemap(directorin) void *;
%typemap(directorout) void * user_cb_data;
%typemap(in) void * user_cb_data;
%typemap(out) void *;
wrap_unique_ptr(DownloadCallbacksUniquePtr, libdnf5::repo::DownloadCallbacks);

%ignore FileDownloadError;
Expand Down

0 comments on commit 3b07d21

Please sign in to comment.