code: def crypto_pwhash_alg(outlen, passwd, salt, opslimit, memlimit, alg):
      
      ensure(isinstance(outlen, integer_types),
             raising=exc.TypeError)
      ensure(isinstance(opslimit, integer_types),
             raising=exc.TypeError)
      ensure(isinstance(memlimit, integer_types),
             raising=exc.TypeError)
      ensure(isinstance(alg, integer_types),
             raising=exc.TypeError)
      ensure(isinstance(passwd, bytes),
             raising=exc.TypeError)
  
      if len(salt) != crypto_pwhash_SALTBYTES:
          raise exc.ValueError("salt must be exactly {0} bytes long".format(
              crypto_pwhash_SALTBYTES))
  
      if outlen < crypto_pwhash_BYTES_MIN:
          raise exc.ValueError(
              'derived key must be at least {0} bytes long'.format(
                  crypto_pwhash_BYTES_MIN))
  
      elif outlen > crypto_pwhash_BYTES_MAX:
          raise exc.ValueError(
              'derived key must be at most {0} bytes long'.format(
                  crypto_pwhash_BYTES_MAX))
  
      _check_argon2_limits_alg(opslimit, memlimit, alg)
  
      outbuf = ffi.new("unsigned char[]", outlen)
  
      ret = lib.crypto_pwhash(outbuf, outlen, passwd, len(passwd),
                              salt, opslimit, memlimit, alg)
  
      ensure(ret == 0, 'Unexpected failure in key derivation',
             raising=exc.RuntimeError)
  
      return ffi.buffer(outbuf, outlen)[:]
docs: Derive a raw cryptographic key using the ``passwd`` and the ``salt``
      given as input to the ``alg`` algorithm.
  
      :param outlen: the length of the derived key
      :type outlen: int
      :param passwd: The input password
      :type passwd: bytes
      :param opslimit: computational cost
      :type opslimit: int
      :param memlimit: memory cost
      :type memlimit: int
      :param alg: algorithm identifier
      :type alg: int
      :return: derived key
      :rtype: bytes