is it though. I have plenty of .h in my /usr/include with copyrights between 1980 and 1985. Sure, it's not modern best practices, but at least it's possible... and for a one-off task there's definitely not much point in doing a wrapper.
Maybe it gives you a raw pointer to new resources. In 2021 those are just loose references which don't signify ownership, you need the wrapper to avoid this confusion leaking into your program.
Maybe it gives you an integer handle which needs to be passed to some other API call to "release" the handle when you're done with it. Again you'll want a wrapper to handle this properly in your code or you may leak resources. You'll also want a wrapper because one integer is the same as another, but you probably shouldn't finished_with_cow(dog_number) or clean_up_dog(cow_number) even though those compile.
Being forty years old it invariably won't be thread safe, so you'd also want to wrap it for that reason unless (as is often the case in C++) your code isn't thread safe anyway.
"at least it's possible" isn't a differentiator. As I said you could also access this 40 year old API from Rust, but you'd want to build a wrapper for it because it the behaviour is so violently different from what's expected in the modern ecosystem.
you can use unique_ptr directly for that. take for instance the 197x API, fopen: you can just do
using file_handle = std::unique_ptr<FILE, decltype([] (FILE* file) { fclose(file); })>;
and then store a file_handle in your class.> Maybe it gives you an integer handle which needs to be passed to some other API call to "release" the handle when you're done with it. Again you'll want a wrapper to handle this properly in your code or you may leak resources. You'll also want a wrapper because one integer is the same as another, but you probably shouldn't finished_with_cow(dog_number) or clean_up_dog(cow_number) even though those compile.
it needs a one-time class to coax an int into behaving like a pointer but otherwise it's the same principle
The point isn't that this is impossible it's that in both cases you want to write a wrapper to use them ergonomically in your modern software, C++ doesn't magically make 1980s code more respectful of object lifetime management than you'd think by reading Stroustrup's book at the time just because modern C++ (and the modern edition of the book) spends more time on this problem.
I think Jason Turner put together a little example about this type of wrapping as the more sane way forward for people who've persuaded themselves they can't stomach a C++ ABI change because they have binaries with no source or their system is too complicated to re-test. Maybe as a C++ Weekly.
In theory. In practice if it's a one-off task I'm definitely not going to bother and will just use the 1981 API directly, especially if it's used in a single file for instance. There's nothing I find more stupid than code style dogmatism - if it compiles it's kosher in the right circumstances.
Naturally you are being pedantic by focusing on exactly 40 years.
This reminds me of BeOS which claimed to be a C++ operating system and had abstract classes like "BStatable" representing things that can be "stat'd" and which comes with a bunch of methods that use out-pointers for integers that can in turn be bit-compared to constants like S_IWUSR. Very C++. Much object orientation. Wow.
[ Behind the scenes of course it's the stat() system call you remember from Unix and C. ]
It's true that there are really significant libraries people care about for C++ and some of those libraries existed five, ten, in a few cases even twenty-five years ago, but the older they are the uglier they get and more likely they are to drive people away from C++ rather than toward it. If your argument becomes something like "Why use Rust when C++ has COM?" you might as well reveal your membership of the Rust Evangelism Strike Force.