In working on the new version of jcBench, I made a decision to continue having the actual benchmarking code in C++ (ie unmanaged code) to promote cross-platform deployments. With Windows Phone 8 getting native code support and my obsession with Silicon Graphics IRIX machines I think this is the best route. That being said, the frontends for jcBench will still definitely be done in C# whenever possible. This brings me to my next topic, getting your C++ Library code to be available to your C# application whether that is a console app, WPF, Windows 8 etc. Surprisingly there is a lot of information out there on this, but none of the examples worked for me. With some trial and error I got it working and figured it might help someone out there. So in your C++ (or C) source file: [cpp] extern "C" {
     __declspec( dllexport ) float runIntegerBenchmark(long numObjects, int numThreads); float runIntegerBenchmark(long numObjects, int numThreads) {
     CPUBenchmark cpuBenchmark = CPUBenchmark(numObjects, numThreads); return cpuBenchmark.runIntegerBenchmark(); }
__declspec( dllexport ) float runFloatingPointBenchmark(long numObjects, int numThreads); float runFloatingPointBenchmark(long numObjects, int numThreads) {
     CPUBenchmark cpuBenchmark = CPUBenchmark(numObjects, numThreads); return cpuBenchmark.runFloatingPointBenchmark(); }
}
[/cpp] Notice the __declspec( dllexport ) function declaration, this is key to telling your C# (or any other language) that this function is exposed externally in the DLL. Something else to keep in mind is the difference in types between variables in C++ and C#. A long for instance in C++ is an Int32 in the CLR. Something to keep in mind if you get something like this thrown in your C# application:
This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature
Then in your C# code:
[DllImport("jcBenchCppLib.dll", CallingConvention = CallingConvention.Cdecl)] public static extern float runIntegerBenchmark(Int32 numObjects, int numThreads); [DllImport("jcBenchCppLib.dll", CallingConvention = CallingConvention.Cdecl)] public static extern float runFloatingPointBenchmark(Int32 numObjects, int numThreads); ]]>
To execute the function, call it like you would a normal function:
lblInteger.Content = runIntegerBenchmark(100000, 6) + " seconds"; ]]>