cython扩散类型的多态性

时间:2019-05-27 10:39:00

标签: cython

我想要一个更通用的cython扩展类型。此扩展名类型的属性之一是double,我希望在需要时将其用作memoryview(double[::1])。

这是一个简单的示例:

import numpy as np
cimport numpy as np
cimport cython

cdef class Test:

    cdef bint numeric
    cdef double du  

    def __init__(self, bint numeric):

        self.numeric = numeric

        if self.numeric:
            self.du = 1

        else:
            self.du = np.ones(10)

    def disp(self)
        print(self.du)

Test(True).disp()   # returns 1
Test(False).disp()  # gives of course an error

我试图将Test的子类更改为du,将double[::1]的类型更改为__init__,并实现了一个新的du,但似乎我们无法覆盖扩展类型的类属性。即使有效,也不会令人满意,因为我真的不希望每种情况都有一个扩展类型。

最好是我的扩展类型直接处理这两种情况(标量du和memoryview namespace Fixed_Dial_DAL { public class Helper { public static string ComputeHash(string plainText, string hashAlgorithm, byte[] saltBytes) { // If salt is not specified, generate it. if (saltBytes == null) { // Define min and max salt sizes. int minSaltSize = 4; int maxSaltSize = 8; // Generate a random number for the size of the salt. Random random = new Random(); int saltSize = random.Next(minSaltSize, maxSaltSize); // Allocate a byte array, which will hold the salt. saltBytes = new byte[saltSize]; // Initialize a random number generator. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); // Fill the salt with cryptographically strong byte values. rng.GetNonZeroBytes(saltBytes); } // Convert plain text into a byte array. byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText); // Allocate array, which will hold plain text and salt. byte[] plainTextWithSaltBytes = new byte[plainTextBytes.Length + saltBytes.Length]; // Copy plain text bytes into resulting array. for (int i = 0; i < plainTextBytes.Length; i++) plainTextWithSaltBytes[i] = plainTextBytes[i]; // Append salt bytes to the resulting array. for (int i = 0; i < saltBytes.Length; i++) plainTextWithSaltBytes[plainTextBytes.Length + i] = saltBytes[i]; HashAlgorithm hash; // Make sure hashing algorithm name is specified. if (hashAlgorithm == null) hashAlgorithm = ""; // Initialize appropriate hashing algorithm class. switch (hashAlgorithm.ToUpper()) { case "SHA384": hash = new SHA384Managed(); break; case "SHA512": hash = new SHA512Managed(); break; default: hash = new MD5CryptoServiceProvider(); break; } // Compute hash value of our plain text with appended salt. byte[] hashBytes = hash.ComputeHash(plainTextWithSaltBytes); // Create array which will hold hash and original salt bytes. byte[] hashWithSaltBytes = new byte[hashBytes.Length + saltBytes.Length]; // Copy hash bytes into resulting array. for (int i = 0; i < hashBytes.Length; i++) hashWithSaltBytes[i] = hashBytes[i]; // Append salt bytes to the result. for (int i = 0; i < saltBytes.Length; i++) hashWithSaltBytes[hashBytes.Length + i] = saltBytes[i]; // Convert result into a base64-encoded string. string hashValue = Convert.ToBase64String(hashWithSaltBytes); // Return the result. return hashValue; } public static bool VerifyHash(string plainText, string hashAlgorithm, string hashValue) { // Convert base64-encoded hash value into a byte array. byte[] hashWithSaltBytes = Convert.FromBase64String(hashValue); // We must know size of hash (without salt). int hashSizeInBits, hashSizeInBytes; // Make sure that hashing algorithm name is specified. if (hashAlgorithm == null) hashAlgorithm = ""; // Size of hash is based on the specified algorithm. switch (hashAlgorithm.ToUpper()) { case "SHA384": hashSizeInBits = 384; break; case "SHA512": hashSizeInBits = 512; break; default: // Must be MD5 hashSizeInBits = 128; break; } // Convert size of hash from bits to bytes. hashSizeInBytes = hashSizeInBits / 8; // Make sure that the specified hash value is long enough. if (hashWithSaltBytes.Length < hashSizeInBytes) return false; // Allocate array to hold original salt bytes retrieved from hash. byte[] saltBytes = new byte[hashWithSaltBytes.Length - hashSizeInBytes]; // Copy salt from the end of the hash to the new array. for (int i = 0; i < saltBytes.Length; i++) saltBytes[i] = hashWithSaltBytes[hashSizeInBytes + i]; // Compute a new hash string. string expectedHashString = ComputeHash(plainText, hashAlgorithm, saltBytes); // If the computed hash matches the specified hash, // the plain text value must be correct. return (hashValue == expectedHashString); } } } using (DataTable dataTable = new DataTable()) { using (DataSet dataSet = new DataSet()) { con.Open(); sqlCommand.Parameters.AddWithValue("@aMail", SqlDbType.NVarChar).Value = aMail; //sqlCommand.Parameters.AddWithValue("@aPassword", SqlDbType.NVarChar).Value = aPassword; sqlCommand.CommandType = CommandType.StoredProcedure; sqlDataAdapter.SelectCommand = sqlCommand; sqlDataAdapter.Fill(dataTable); sqlDataAdapter.Fill(dataSet); con.Close(); string adminPassword = dataTable.Rows[0].Field<string>("aPassword"); bool flag = Helper.VerifyHash(aPassword, "SHA512", adminPassword); // bool loginSuccessful = ((dataSet.Tables.Count > 0) && (dataSet.Tables[0].Rows.Count > 0)); return flag; )。

有没有办法用Cython做到这一点?

1 个答案:

答案 0 :(得分:1)

不幸的是,您不能使用fused_type作为属性类型。您可以在此处有两个选择:

您可以尝试使用要调用的变量的内存地址,并在需要时进行强制转换(所有内容都在here中进行了说明。)不幸的是,我未能成功使它与类型化的内存视图一起使用。

或者您可以使用定义的属性数字来调用适当的方法:

import numpy as np
cimport numpy as np
cimport cython

cdef class Test:

    cdef bint numeric
    cdef double du_numeric
    cdef double[:] du_mem_view

    def __init__(self, bint numeric):

        self.numeric = numeric

        if self.numeric:
            self.du_numeric = 1

        else:
            self.du_mem_view = np.ones(10)

    def disp(self):
        if self.numeric:
            print(self.du_numeric)
        else:
            print(self.du_numeric_mem_view)

Test(True).disp()   # returns 1
Test(False).disp()  # Does not give an error anymore !