Es gibt Antworten auf SO, die während der Laufzeit (nicht verwalteten) Assembly-Code erzeugen, den verwalteter Code zurückrufen kann. Das ist alles sehr interessant, aber ich schlage vor, dass Sie einfach C++/CLI für diesen Zweck verwenden, weil es entworfen wurde, um Interop-Szenarien zu vereinfachen. Erstellen Sie eine neue Visual C++ CLR Klassenbibliothek und gibt ihm eine einziges rdrandwrapper.cpp
:
#include <immintrin.h>
using namespace System;
namespace RdRandWrapper {
#pragma managed(push, off)
bool getRdRand(unsigned int* pv) {
const int max_rdrand_tries = 10;
for (int i = 0; i < max_rdrand_tries; ++i) {
if (_rdrand32_step(pv)) return true;
}
return false;
}
#pragma managed(pop)
public ref class RandomGeneratorError : Exception
{
public:
RandomGeneratorError() : Exception() {}
RandomGeneratorError(String^ message) : Exception(message) {}
};
public ref class RdRandom
{
public:
int Next() {
unsigned int v;
if (!getRdRand(&v)) {
throw gcnew RandomGeneratorError("Failed to get hardware RNG number.");
}
return v & 0x7fffffff;
}
};
}
Dies ist eine sehr nackte Knochen-Implementierung, die nur Random.Next
in immer eine einzige nicht-negative Zufallszahl zu imitieren versucht. Pro Frage, es versucht nicht zu überprüfen, dass RDRAND
tatsächlich auf der CPU verfügbar ist, aber es behandelt den Fall, in dem der Befehl vorhanden ist aber nicht funktioniert. (Dies kann auf der aktuellen Hardware nicht passieren, es sei denn, es ist defekt, wie detailliert here.)
Die resultierende Assembly ist eine gemischte Assembly, die von verwaltetem C# -Code verbraucht werden kann. Stellen Sie sicher, dass Sie Ihre Assembly als x86 oder x64 kompilieren, genau wie Ihr nicht verwalteter Code (standardmäßig werden Projekte als "Any CPU" kompiliert, was nicht korrekt funktioniert, da der nicht verwaltete Code nur eine bestimmte Bitness aufweist).
using System;
using RdRandWrapper;
class Program {
static void Main(string[] args) {
var r = new RdRandom();
for (int i = 0; i != 10; ++i) {
Console.WriteLine(r.Next());
}
}
}
Ich mache keine Ansprüche hinsichtlich Leistung, aber es ist wahrscheinlich nicht so toll. Wenn Sie viele zufällige Werte auf diese Weise erhalten möchten, möchten Sie wahrscheinlich eine Next(int[] values)
Überladung, um viele zufällige Werte in einem Aufruf zu erhalten, um den Overhead von Interop zu reduzieren.
Verwenden Sie einfach ['RNGCryptoServiceProvider'] (https://msdn.microsoft.com/library/system.security.cryptography.rngcrptoserviceprovider), was für die meisten Zwecke, die besser als Pseudozufallszahlen benötigen, gut genug sein sollte. –
@JeroenMostert Vielen Dank für Ihren Kommentar. Aber ich brauche es wirklich zufällig, um den Zweck wissenschaftlich genauer Softwareexperimente zu erfüllen. Ich habe TrueRNGV3 bestellt, aber es könnte zu lange dauern, bis ich eintrifft und ich habe in der Zwischenzeit nach Alternativen gesucht und RDRAND scheint vielversprechend. –
Sie können keine prozessorspezifische Assembly in C# ausführen. Sie können einen Teil von C++ - Code dafür schreiben und diesen mit C++/CLI oder P/Invoke umhüllen, wie hier beschrieben (https://stackoverflow.com/questions/13436130/). –