[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: C# wrapper of apt library libapt-pkg



Hi David


Thanks for your comments and feedback.

 

I might have been a little naïve. I was hoping I "just" had to pinvoke libapt-pkg in C# and instantiate some classes and call some functions, just as I do with python-apt, but there seem to be more to it :-/


And it's not just a matter of optimization, but also to have something working stable.

Calling the python-apt from python.net (embedding python in C#) has some instability issues that I can't get rid off, so I thought about alternatives.


I also took a look at the format of the cache file (/var/cache/apt/pkgcache.bin) to investigate the possibility of reading the file directly in C#. But serializing/converting those C/C++ objects in binary format to C# objects, e.g the HashTable containing all package indexes, seem to be huge challenge too.

The format seemed to be described here: http://www.fifi.org/doc/libapt-pkg-doc/cache.html/ch2.html


So maybe my best option is to get python-net to work better (the problems are not related to python-apt)


/Brian


On Fri, Nov 19, 2021 at 5:10 PM David Kalnischkies <david@kalnischkies.de> wrote:
On Wed, Nov 17, 2021 at 11:23:00PM +0100, BW wrote:
> But I would like to pinvoke the apt library directly for better resource
> use, performance and stability.
> Is it correct I should target libapt-pkg.so?

Do you objectively need "better" or could this be described as premature
optimisation?

You mention later that you have not a lot of experience with C/C++, so
the investment in becoming fluent in it might very well offset any gain
you might hope to achieve by going this route in the first place.


> And using python.net>python-apt I retrieved all package-names by first
> initializing the class Cache() and then call Cache.keys().
> Can anyone point me in the right direction how to do the same by pinvoke
> libapt-pkg?

The higher level API of python-apt hides a lot of nitty gritty details
(at least I assume as much, I do not have much experience with python
 myself).

libapt-pkg can be considerably more low level as it makes far less
assumptions about how it is going to be used.


The following is a little program which prints every package name known
to apt. Note that this includes purely virtual names and that I chose to
iterate over the Group structure (Grp) here as that one has the name
field and "groups" the packages with the same name together (in apt,
due to reasons, a Package exists for every architecture) so iterating
packages would potentially give me foo:amd64,foo:i386,foo:armel,…

```
/tmp$ cat pkgnames.cc
#include <apt-pkg/cachefile.h>
#include <apt-pkg/init.h>
#include <apt-pkg/pkgsystem.h>
#include <iostream>

int main() {
  pkgInitConfig(*_config);
  pkgInitSystem(*_config, _system);

  pkgCacheFile CacheFile;
  if (not CacheFile.BuildCaches(nullptr, false))
    return 1;

  for (auto Grp = CacheFile.GetPkgCache()->GrpBegin(); not Grp.end(); ++Grp)
    std::cout << Grp.Name() << '\n';

  return 0;
}
/tmp$ g++ -o pkgnames -Wall -Wextra pkgnames.cc -lapt-pkg
/tmp$ ./pkgnames | less
```

If you are serious in going this route have a look at the code of the
apt commandline tools in cmdline/ and apt-private/. Perhaps find the
code for "apt-cache pkgnames". It does more than the code above, but you
have at least a rough idea now how it works. If you understand that one,
you are one step closer to understand the monster behind 'apt install'
in some far away future… 😉

If you are stuck feel free to ask here on list or in #debian-apt on IRC.
The same is true if you decide to stick to python for now btw.


Best regards

David Kalnischkies

Reply to: