HOWTO: Using Core Temp shared memory with C++

Updates on developement of new features and user input/requests

Moderator: imposter

Post Reply
CoreTemp-User315
Registered User
Registered User
Posts: 5
Joined: Thu Jan 01, 1970 12:00 am

HOWTO: Using Core Temp shared memory with C++

Post by CoreTemp-User315 »

This describes how to use the Core Temp shared memory API with Visual C++. A similar method can be used for any other compiler (difference is import library tool and #pragma directives). Since there were a couple of steps involved, I figure I'd share it here.

This assumes basic knowledge of creating and using DLLs and libraries.

Note that this is C++, not C. If you are programming in C there are some trivial changes (use typedef to declare struct, don't specify extern "C").

Step 1: Download the DLL

You can get it here. Use the 32-bit or 64-bit version as necessary (I have not tried the 64-bit version).

The DLL comes with a LIB file. Ignore it, it exports functions using C++ mangled names that probably aren't compatible with the linker you are using (well you can try to use it if you want, and if it works then you can skip step 2). The only thing you need from the zip file is the one DLL you are using.

Step 2: Generate import library for DLL

Next step is to generate a proper LIB file for the DLL for the compiler/linker you are using. Most compilers also ship with a tool that can generate import libraries from DLLs. Visual Studio comes with a command line tool called lib.

You will need to create a module definition file. In notepad make a file named GetCoreTempInfo.def in the same directory you put GetCoreTempInfo.dll in and put this text in it:

Code: Select all

EXPORTS
	fnGetCoreTempInfoAlt@4=fnGetCoreTempInfoAlt	@2
Then start up a command prompt, change to the directory the DLL is in, and use the lib tool to generate an import library (note: this assumes the lib tool is in your path, which it should be with any proper Visual Studio installation -- if not search for lib.exe in the VS install folder in Program Files and you'll find it):

Code: Select all

lib /DEF:GetCoreTempInfo.def /OUT:GetCoreTempInfo.lib
Tada, now you have a working import library. Note that depending on your linker, if you get undefined references to things like _fnGetCoreTempInfoAlt@4 or whatever, you may have to muck around with your .def file a bit until you get it right. Just put whatever symbol name it's looking for before the = sign (note that the lib tool generally adds an underscore before the exported name).

Note: We're using the fnGetCoreTempInfoAlt function because it has the calling convention specified (WINAPI). The other one, fnGetCoreTempInfo, does not, and so it's up to the compiler. The Core Temp DLL interface is a bit sloppy but it's no big deal.

Note: You don't have to create an import library, but it makes using the DLL a lot more convenient. Alternatively you can use LoadLibrary/GetProcAddress to load the library yourself and get the fnGetCoreTempInfoAlt function. I'd just use the import library, which takes care of that for you.

Step 3: Declare DLL structures and functions.

Next put the declarations for the data structure and the fnGetCoreTempInfoAlt in your code somewhere. I'd just make a header containing the declarations. With Visual C++, the following declarations will work:

Code: Select all

#include <windows.h> // see note 1
#pragma comment (lib, "GetCoreTempInfo.lib") // see note 2
#pragma pack (push, 4) // see note 3

// see note 4
struct CORE_TEMP_SHARED_DATA {
	DWORD       uiLoad[256];    // one per core
	DWORD       uiTjMax[128];   // one per cpu
	DWORD       uiCoreCnt;
	DWORD       uiCPUCnt;
	FLOAT       fTemp[256];     // one per core
	FLOAT       fVID;
	FLOAT       fCPUSpeed;
	FLOAT       fFSBSpeed;
	FLOAT       fMultipier;	
	CHAR        sCPUName[100];
	BYTE        ucFahrenheit;
	BYTE        ucDeltaToTjMax;
};

// see note 5
extern "C" bool WINAPI fnGetCoreTempInfoAlt(CORE_TEMP_SHARED_DATA *pData);

#pragma pack (pop)
Notes:
  1. If you do not want to include windows.h, you will have to replace the types with appropriate types for 32-bit integers, 32-bit IEEE floats, and 8-bit chars, and replace WINAPI with __stdcall (or equivalent for your compiler).
  2. In VC++ this will cause the linker to link to GetCoreTempInfo.lib. If your compiler does not have this #pragma (or a similar one) then you'll have to get rid of this and link to the lib explicitly (e.g. set it in project options in VC++, specify it on command line to GCC, etc.).
  3. In VC++ this sets the structure byte alignment to 4. Unfortunately, the Core Temp API spec doesn't explicitly state the alignment, so assume that this value could conceivably change in future releases of the Core Temp DLL (which would suck and break your code -- sadly there's no way to specify the version of the structure you want either so if the API changes in the future it will also break all existing code). If you don't have this #pragma use whatever one is appropriate for your compiler.
  4. Don't just blindly use the struct declaration on the Core Temp API page (although it does state the size of ints and chars it doesn't reflect that in the declaration), as the size of int, float, and char can vary from platform to platform. Instead, here we use the data types from windows.h which have guaranteed sizes on any platform.
  5. We use extern "C" to force the mangled name to be something more predictable, since C name mangling is generally much more consistent across compilers than C++ mangling. This is what causes the function to be named "_fnGetCoreTempInfoAlt@4" in the lib.
Step 5: Use the API.

After this, it's simple. If you don't have the #pragma comment directive above, don't forget to link to GetCoreTempInfo.lib. Include the declarations above, and then you can simply do this:

Code: Select all

CORE_TEMP_SHARED_DATA ct;

if (fnGetCoreTempInfoAlt(&ct)) {
  // process ct
} else {
  // GetLastError() contains error code
}
That's it. If you create the LIB file above and stick the declarations in a header you won't have to go through all these steps again unless you change compilers, you can just reuse the library and headers.

If anybody has any questions post them here, although I will personally not be checking this thread very often.


Suggestions to improve Core Temp API

That's it for the howto. These are some of my suggestions for improving the Core Temp API, which seems to have a lot of classic DLL design problems:
  • Specify structure byte alignment in docs.
  • C/C++ specific: Use platform-independent data types such as DWORD, FLOAT, and CHAR (declared in windows.h) in the struct definition.
  • Use a well-specified return type from fnGetCoreTempInfoAlt instead of "bool", which doesn't have a standardized size (e.g. use BOOL from windows.h, or specify it as a 32-bit int or something).
  • Put an API version or structure size field as the first field in the struct, that way if the struct layout changes in the future the DLL implementation can handle this to maintain backward compatibility and application code will never have to change.
  • C/C++ specific: Just for convenience for developers, distribute a header and some import libraries for various compilers on the Core Temp API page (this howto wouldn't be necessary then).
  • Always explicitly specify a calling convention, and use one that's generally widely supported across many compilers (e.g. stdcall, which WINAPI is #defined for... fnGetCoreTempInfoAlt is good, fnGetCoreTempInfo is not).

Post Reply

Return to “Core Temp - Development”