Click here to Skip to main content
15,887,683 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I can't manage to PInvoke properly the C Rand and SRand functions.
I tried in both x64 and x86 modes but I get either unbalanced stacks or just two digits numbers (38 41 45...).
I believe we should be expecting much bigger numbers 0<=n<2^32.

Can anyone spot the problem:

X64
C#
//[DllImport(@"C:\Windows\SysWOW64\msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
[DllImport(@"C:\Windows\System32\msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int64 srand(UInt64 seed);

//[DllImport(@"C:\Windows\SysWOW64\msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
[DllImport(@"C:\Windows\System32\msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int64 rand();


public static void Main()
{
    for (uint i = 0; i < 10; i++)
    {
        srand(i);
        Console.WriteLine(rand());
    }

}



X86
C#
[DllImport(@"C:\Windows\SysWOW64\msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
//[DllImport(@"C:\Windows\System32\msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int64 srand(UInt32 seed);

[DllImport(@"C:\Windows\SysWOW64\msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
//[DllImport(@"C:\Windows\System32\msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern Int32 rand();


public static void Main()
{
    for (uint i = 0; i < 10; i++)
    {
        srand(i);
        Console.WriteLine(rand());
    }

}
Posted

1 solution

Yes, I can see a couple of problems right now.

The path "C:\Windows\System32\msvcrt.dll" is not portable. System32 can actually be installed in any directory. As this is Windows API, the usual appropriate and valid technique is using a file name without full path. It should be resolved in 32-bit version on 32-bit system and 64-bit version on 64-bit system. However, this is not a source of your problem. I hope you also know that you cannot mix different instruction-set target architectures in the same process. The assembly may compile, but this would lead to a crash during run time.

As this is Windows API, you need to use System.Runtime.InteropServices.StdCall. This the default convention for Windows OS calls, so you can simply omit this parameter. See http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention.aspx[^]. Most likely, the problem you observe is due to wrong calling conventions.

Why not staying with platform-portable solution by using the .NET class System.Random, http://msdn.microsoft.com/en-us/library/system.random.aspx[^]? Well, some say that statistical quality of this generator is not perfect, but what tells you that msvcrt.dll rand is any better?

For example, take a look at this CodeProject articles:
Simple Random Number Generation[^],
Pitfalls in Random Number Generation[^].


—SA
 
Share this answer
 
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900