| # This file is dual licensed under the terms of the Apache License, Version |
| # 2.0, and the BSD License. See the LICENSE file in the root of this repository |
| # for complete details. |
| |
| from __future__ import annotations |
| |
| import os |
| import platform |
| import sys |
| |
| from cffi import FFI |
| |
| # Load the cryptography __about__ to get the current package version |
| base_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) |
| about: dict = {} |
| with open(os.path.join(base_src, "cryptography", "__about__.py")) as f: |
| exec(f.read(), about) |
| |
| |
| def build_ffi_for_binding( |
| module_name: str, |
| module_prefix: str, |
| modules: list[str], |
| ): |
| """ |
| Modules listed in ``modules`` should have the following attributes: |
| |
| * ``INCLUDES``: A string containing C includes. |
| * ``TYPES``: A string containing C declarations for types. |
| * ``FUNCTIONS``: A string containing C declarations for functions & macros. |
| * ``CUSTOMIZATIONS``: A string containing arbitrary top-level C code, this |
| can be used to do things like test for a define and provide an |
| alternate implementation based on that. |
| """ |
| types = [] |
| includes = [] |
| functions = [] |
| customizations = [] |
| for name in modules: |
| __import__(module_prefix + name) |
| module = sys.modules[module_prefix + name] |
| |
| types.append(module.TYPES) |
| functions.append(module.FUNCTIONS) |
| includes.append(module.INCLUDES) |
| customizations.append(module.CUSTOMIZATIONS) |
| |
| verify_source = "\n".join(includes + customizations) |
| return build_ffi( |
| module_name, |
| cdef_source="\n".join(types + functions), |
| verify_source=verify_source, |
| ) |
| |
| |
| def build_ffi( |
| module_name: str, |
| cdef_source: str, |
| verify_source: str, |
| ): |
| ffi = FFI() |
| # Always add the CRYPTOGRAPHY_PACKAGE_VERSION to the shared object |
| cdef_source += "\nstatic const char *const CRYPTOGRAPHY_PACKAGE_VERSION;" |
| verify_source += '\n#define CRYPTOGRAPHY_PACKAGE_VERSION "{}"'.format( |
| about["__version__"] |
| ) |
| if platform.python_implementation() == "PyPy": |
| verify_source += r""" |
| int Cryptography_make_openssl_module(void) { |
| int result; |
| |
| Py_BEGIN_ALLOW_THREADS |
| result = cffi_start_python(); |
| Py_END_ALLOW_THREADS |
| |
| return result; |
| } |
| """ |
| ffi.cdef(cdef_source) |
| ffi.set_source( |
| module_name, |
| verify_source, |
| ) |
| return ffi |