问题
I wrote function that encrypts/decrypts a buffer (2 versions of the same function - first, with cryptopp, second - with openssl).
I would like to make something like this:
#if defined OPENSSL
run_aes_openssl(...);
#elif defined CRYPTOPP
run_aes_crytopp(...);
#else
error(...);
#end
Is it possible?
回答1:
It's not quite that simple. In order to find that a macro is defined, you have to include the header that defines that macro. And C doesn't have anything like "include foo.h iff it exists"; it has to exist otherwise there is a compilation error.
Normally this would be sorted out by a script that you run before compilation. Your script checks locations like /usr/include
, /usr/local/include
, etc., to see if the OpenSSL headers are there; and then it outputs a Makefile which contains in the CFLAGS -DHAVE_OPENSSL
. Then your code can check for that macro.
This is quite a bit of hullabaloo, to keep things simple you could require the user to manually edit a file , e.g. distribute your project with something called user_config.h
that the user is supposed to edit before compiling, to specify where they put OpenSSL and so on.
There is a preset system called GNU Autoconf which contains a script that checks your system for everything under the sun. This has its advantages and disadvantages; it makes things easier for plebs downloading your source code, but it is bloaty and can be hard work for yourself.
回答2:
How to check if openssl or cryptopp is installed and use the library that actually exists in the system (is installed)?
If your application was built on the system it is running, then the code you have shown is OK. Presumably, the build system will detect both OpenSSL and Crypto++. In the case both are available, it looks like your code will favor OpenSSL.
If you application is built elsewhere and needs to check at runtime, then you will need dlopen, dlsym
, dlclose
and friends.
In the case of runtime checking, its probably best to build a dispatch table and call through it. For example, you might have a table with function pointers to your internal run_aes_openssl
, run_aes_crytopp
, etc.
Upon startup, you populate the table based on the results of dlopen
. If you find OpenSSL, then you populate your table with the OpenSSL gear. If you find Crypto++, then you populate your table with the Crypto++ gear.
C++ can be painful to use with dlopen
and friends because of name mangling. Worse, the mangling differs between distributions and runtime library versions. For example, here's a function to generate a private RSA key:
RSA::PrivateKey key;
key.GenerateRandomWithKeySize(prng, 1024);
And here's the corresponding function names on Mac OS X. Debian and Red Hat will likely be different.
$ nm cryptopp-test.exe | grep -i GenerateRandom | grep -i RSA
00000001000c7d80 T __ZN8CryptoPP21InvertibleRSAFunction14GenerateRandomERNS_21RandomNumberGeneratorERKNS_14NameValuePairsE
00000001000c8eb0 T __ZThn120_N8CryptoPP21InvertibleRSAFunction14GenerateRandomERNS_21RandomNumberGeneratorERKNS_14NameValuePairsE
来源:https://stackoverflow.com/questions/24310353/how-to-check-if-openssl-or-cryptopp-is-installed-and-use-the-library-that-actual