'Build the wrapper'

def __init__(self, library):

    self._lib = ctypes.CDLL(library)
    (self._version, self._hexversion, self._cflags) = get_version(self._lib)
    self._libreSSL = self._version.startswith('LibreSSL')
    self.pointer = ctypes.pointer
    self.c_int = ctypes.c_int
    self.byref = ctypes.byref
    self.create_string_buffer = ctypes.create_string_buffer
    self.BN_new = self._lib.BN_new
    self.BN_new.restype = ctypes.c_void_p
    self.BN_new.argtypes = []
    self.BN_free = self._lib.BN_free
    self.BN_free.restype = None
    self.BN_free.argtypes = [ctypes.c_void_p]
    self.BN_num_bits = self._lib.BN_num_bits
    self.BN_num_bits.restype = ctypes.c_int
    self.BN_num_bits.argtypes = [ctypes.c_void_p]
    self.BN_bn2bin = self._lib.BN_bn2bin
    self.BN_bn2bin.restype = ctypes.c_int
    self.BN_bn2bin.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    self.BN_bin2bn = self._lib.BN_bin2bn
    self.BN_bin2bn.restype = ctypes.c_void_p
    self.BN_bin2bn.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
    self.EC_KEY_free = self._lib.EC_KEY_free
    self.EC_KEY_free.restype = None
    self.EC_KEY_free.argtypes = [ctypes.c_void_p]
    self.EC_KEY_new_by_curve_name = self._lib.EC_KEY_new_by_curve_name
    self.EC_KEY_new_by_curve_name.restype = ctypes.c_void_p
    self.EC_KEY_new_by_curve_name.argtypes = [ctypes.c_int]
    self.EC_KEY_generate_key = self._lib.EC_KEY_generate_key
    self.EC_KEY_generate_key.restype = ctypes.c_int
    self.EC_KEY_generate_key.argtypes = [ctypes.c_void_p]
    self.EC_KEY_check_key = self._lib.EC_KEY_check_key
    self.EC_KEY_check_key.restype = ctypes.c_int
    self.EC_KEY_check_key.argtypes = [ctypes.c_void_p]
    self.EC_KEY_get0_private_key = self._lib.EC_KEY_get0_private_key
    self.EC_KEY_get0_private_key.restype = ctypes.c_void_p
    self.EC_KEY_get0_private_key.argtypes = [ctypes.c_void_p]
    self.EC_KEY_get0_public_key = self._lib.EC_KEY_get0_public_key
    self.EC_KEY_get0_public_key.restype = ctypes.c_void_p
    self.EC_KEY_get0_public_key.argtypes = [ctypes.c_void_p]
    self.EC_KEY_get0_group = self._lib.EC_KEY_get0_group
    self.EC_KEY_get0_group.restype = ctypes.c_void_p
    self.EC_KEY_get0_group.argtypes = [ctypes.c_void_p]
    self.EC_POINT_get_affine_coordinates_GFp = self._lib.EC_POINT_get_affine_coordinates_GFp
    self.EC_POINT_get_affine_coordinates_GFp.restype = ctypes.c_int
    self.EC_POINT_get_affine_coordinates_GFp.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key
    self.EC_KEY_set_private_key.restype = ctypes.c_int
    self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    self.EC_KEY_set_public_key = self._lib.EC_KEY_set_public_key
    self.EC_KEY_set_public_key.restype = ctypes.c_int
    self.EC_KEY_set_public_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    self.EC_KEY_set_group = self._lib.EC_KEY_set_group
    self.EC_KEY_set_group.restype = ctypes.c_int
    self.EC_KEY_set_group.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    self.EC_POINT_set_affine_coordinates_GFp = self._lib.EC_POINT_set_affine_coordinates_GFp
    self.EC_POINT_set_affine_coordinates_GFp.restype = ctypes.c_int
    self.EC_POINT_set_affine_coordinates_GFp.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    self.EC_POINT_new = self._lib.EC_POINT_new
    self.EC_POINT_new.restype = ctypes.c_void_p
    self.EC_POINT_new.argtypes = [ctypes.c_void_p]
    self.EC_POINT_free = self._lib.EC_POINT_free
    self.EC_POINT_free.restype = None
    self.EC_POINT_free.argtypes = [ctypes.c_void_p]
    self.BN_CTX_free = self._lib.BN_CTX_free
    self.BN_CTX_free.restype = None
    self.BN_CTX_free.argtypes = [ctypes.c_void_p]
    self.EC_POINT_mul = self._lib.EC_POINT_mul
    self.EC_POINT_mul.restype = None
    self.EC_POINT_mul.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    self.EC_KEY_set_private_key = self._lib.EC_KEY_set_private_key
    self.EC_KEY_set_private_key.restype = ctypes.c_int
    self.EC_KEY_set_private_key.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    if ((self._hexversion >= 269484032) and (not self._libreSSL)):
        self.EC_KEY_OpenSSL = self._lib.EC_KEY_OpenSSL
        self._lib.EC_KEY_OpenSSL.restype = ctypes.c_void_p
        self._lib.EC_KEY_OpenSSL.argtypes = []
        self.EC_KEY_set_method = self._lib.EC_KEY_set_method
        self._lib.EC_KEY_set_method.restype = ctypes.c_int
        self._lib.EC_KEY_set_method.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    else:
        self.ECDH_OpenSSL = self._lib.ECDH_OpenSSL
        self._lib.ECDH_OpenSSL.restype = ctypes.c_void_p
        self._lib.ECDH_OpenSSL.argtypes = []
        self.ECDH_set_method = self._lib.ECDH_set_method
        self._lib.ECDH_set_method.restype = ctypes.c_int
        self._lib.ECDH_set_method.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    self.BN_CTX_new = self._lib.BN_CTX_new
    self._lib.BN_CTX_new.restype = ctypes.c_void_p
    self._lib.BN_CTX_new.argtypes = []
    self.ECDH_compute_key = self._lib.ECDH_compute_key
    self.ECDH_compute_key.restype = ctypes.c_int
    self.ECDH_compute_key.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p]
    self.EVP_CipherInit_ex = self._lib.EVP_CipherInit_ex
    self.EVP_CipherInit_ex.restype = ctypes.c_int
    self.EVP_CipherInit_ex.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    self.EVP_CIPHER_CTX_new = self._lib.EVP_CIPHER_CTX_new
    self.EVP_CIPHER_CTX_new.restype = ctypes.c_void_p
    self.EVP_CIPHER_CTX_new.argtypes = []
    self.EVP_aes_128_cfb128 = self._lib.EVP_aes_128_cfb128
    self.EVP_aes_128_cfb128.restype = ctypes.c_void_p
    self.EVP_aes_128_cfb128.argtypes = []
    self.EVP_aes_256_cfb128 = self._lib.EVP_aes_256_cfb128
    self.EVP_aes_256_cfb128.restype = ctypes.c_void_p
    self.EVP_aes_256_cfb128.argtypes = []
    self.EVP_aes_128_cbc = self._lib.EVP_aes_128_cbc
    self.EVP_aes_128_cbc.restype = ctypes.c_void_p
    self.EVP_aes_128_cbc.argtypes = []
    self.EVP_aes_256_cbc = self._lib.EVP_aes_256_cbc
    self.EVP_aes_256_cbc.restype = ctypes.c_void_p
    self.EVP_aes_256_cbc.argtypes = []
    self.EVP_aes_128_ofb = self._lib.EVP_aes_128_ofb
    self.EVP_aes_128_ofb.restype = ctypes.c_void_p
    self.EVP_aes_128_ofb.argtypes = []
    self.EVP_aes_256_ofb = self._lib.EVP_aes_256_ofb
    self.EVP_aes_256_ofb.restype = ctypes.c_void_p
    self.EVP_aes_256_ofb.argtypes = []
    self.EVP_bf_cbc = self._lib.EVP_bf_cbc
    self.EVP_bf_cbc.restype = ctypes.c_void_p
    self.EVP_bf_cbc.argtypes = []
    self.EVP_bf_cfb64 = self._lib.EVP_bf_cfb64
    self.EVP_bf_cfb64.restype = ctypes.c_void_p
    self.EVP_bf_cfb64.argtypes = []
    self.EVP_rc4 = self._lib.EVP_rc4
    self.EVP_rc4.restype = ctypes.c_void_p
    self.EVP_rc4.argtypes = []
    if ((self._hexversion >= 269484032) and (not self._libreSSL)):
        self.EVP_CIPHER_CTX_reset = self._lib.EVP_CIPHER_CTX_reset
        self.EVP_CIPHER_CTX_reset.restype = ctypes.c_int
        self.EVP_CIPHER_CTX_reset.argtypes = [ctypes.c_void_p]
    else:
        self.EVP_CIPHER_CTX_cleanup = self._lib.EVP_CIPHER_CTX_cleanup
        self.EVP_CIPHER_CTX_cleanup.restype = ctypes.c_int
        self.EVP_CIPHER_CTX_cleanup.argtypes = [ctypes.c_void_p]
    self.EVP_CIPHER_CTX_free = self._lib.EVP_CIPHER_CTX_free
    self.EVP_CIPHER_CTX_free.restype = None
    self.EVP_CIPHER_CTX_free.argtypes = [ctypes.c_void_p]
    self.EVP_CipherUpdate = self._lib.EVP_CipherUpdate
    self.EVP_CipherUpdate.restype = ctypes.c_int
    self.EVP_CipherUpdate.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
    self.EVP_CipherFinal_ex = self._lib.EVP_CipherFinal_ex
    self.EVP_CipherFinal_ex.restype = ctypes.c_int
    self.EVP_CipherFinal_ex.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    self.EVP_DigestInit = self._lib.EVP_DigestInit
    self.EVP_DigestInit.restype = ctypes.c_int
    self._lib.EVP_DigestInit.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    self.EVP_DigestInit_ex = self._lib.EVP_DigestInit_ex
    self.EVP_DigestInit_ex.restype = ctypes.c_int
    self._lib.EVP_DigestInit_ex.argtypes = (3 * [ctypes.c_void_p])
    self.EVP_DigestUpdate = self._lib.EVP_DigestUpdate
    self.EVP_DigestUpdate.restype = ctypes.c_int
    self.EVP_DigestUpdate.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int]
    self.EVP_DigestFinal = self._lib.EVP_DigestFinal
    self.EVP_DigestFinal.restype = ctypes.c_int
    self.EVP_DigestFinal.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    self.EVP_DigestFinal_ex = self._lib.EVP_DigestFinal_ex
    self.EVP_DigestFinal_ex.restype = ctypes.c_int
    self.EVP_DigestFinal_ex.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    self.ECDSA_sign = self._lib.ECDSA_sign
    self.ECDSA_sign.restype = ctypes.c_int
    self.ECDSA_sign.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_void_p]
    self.ECDSA_verify = self._lib.ECDSA_verify
    self.ECDSA_verify.restype = ctypes.c_int
    self.ECDSA_verify.argtypes = [ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
    if ((self._hexversion >= 269484032) and (not self._libreSSL)):
        self.EVP_MD_CTX_new = self._lib.EVP_MD_CTX_new
        self.EVP_MD_CTX_new.restype = ctypes.c_void_p
        self.EVP_MD_CTX_new.argtypes = []
        self.EVP_MD_CTX_reset = self._lib.EVP_MD_CTX_reset
        self.EVP_MD_CTX_reset.restype = None
        self.EVP_MD_CTX_reset.argtypes = [ctypes.c_void_p]
        self.EVP_MD_CTX_free = self._lib.EVP_MD_CTX_free
        self.EVP_MD_CTX_free.restype = None
        self.EVP_MD_CTX_free.argtypes = [ctypes.c_void_p]
        self.EVP_sha1 = self._lib.EVP_sha1
        self.EVP_sha1.restype = ctypes.c_void_p
        self.EVP_sha1.argtypes = []
        self.digest_ecdsa_sha1 = self.EVP_sha1
    else:
        self.EVP_MD_CTX_create = self._lib.EVP_MD_CTX_create
        self.EVP_MD_CTX_create.restype = ctypes.c_void_p
        self.EVP_MD_CTX_create.argtypes = []
        self.EVP_MD_CTX_init = self._lib.EVP_MD_CTX_init
        self.EVP_MD_CTX_init.restype = None
        self.EVP_MD_CTX_init.argtypes = [ctypes.c_void_p]
        self.EVP_MD_CTX_destroy = self._lib.EVP_MD_CTX_destroy
        self.EVP_MD_CTX_destroy.restype = None
        self.EVP_MD_CTX_destroy.argtypes = [ctypes.c_void_p]
        self.EVP_ecdsa = self._lib.EVP_ecdsa
        self._lib.EVP_ecdsa.restype = ctypes.c_void_p
        self._lib.EVP_ecdsa.argtypes = []
        self.digest_ecdsa_sha1 = self.EVP_ecdsa
    self.RAND_bytes = self._lib.RAND_bytes
    self.RAND_bytes.restype = ctypes.c_int
    self.RAND_bytes.argtypes = [ctypes.c_void_p, ctypes.c_int]
    self.EVP_sha256 = self._lib.EVP_sha256
    self.EVP_sha256.restype = ctypes.c_void_p
    self.EVP_sha256.argtypes = []
    self.i2o_ECPublicKey = self._lib.i2o_ECPublicKey
    self.i2o_ECPublicKey.restype = ctypes.c_void_p
    self.i2o_ECPublicKey.argtypes = [ctypes.c_void_p, ctypes.c_void_p]
    self.EVP_sha512 = self._lib.EVP_sha512
    self.EVP_sha512.restype = ctypes.c_void_p
    self.EVP_sha512.argtypes = []
    self.HMAC = self._lib.HMAC
    self.HMAC.restype = ctypes.c_void_p
    self.HMAC.argtypes = [ctypes.c_void_p, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_void_p]
    try:
        self.PKCS5_PBKDF2_HMAC = self._lib.PKCS5_PBKDF2_HMAC
    except:
        self.PKCS5_PBKDF2_HMAC = self._lib.PKCS5_PBKDF2_HMAC_SHA1
    self.PKCS5_PBKDF2_HMAC.restype = ctypes.c_int
    self.PKCS5_PBKDF2_HMAC.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_int, ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
    self._set_ciphers()
    self._set_curves()
