我想要一个更通用的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做到这一点?
答案 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 !