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 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