Posts Tagged ‘ Example ’

Beep! Beep!

So I wrote a post about creating basic beeping sounds in C# a few months ago:
https://inphamousdevelopment.wordpress.com/2012/05/07/console-beep-for-64-bit-windows/

Well, someone asked me if I could make the source code available. Well, because I’m a nice guy, I’ve cleaned up the project and uploaded it here:

http://phamous-apps.com/wordpress/MusicBeeperPA.zip

You will need Visual Studio 2010 or newer to run the project as-is. I have not tested it in Mono, and I do not guarantee that it will work in Mono. The code is offered AS-IS WITH NO SUPPORT.

If you find the project useful, please make a video response to the YouTube video with your creation.

Sending callbacks from C# to C++

Some days you just have to work with old methods to get the job done. I am working on a project that needs to be in native C++ for legacy reasons, but would prefer to bring it to the modern era of programming by using C#. I wanted a way to get data from the native classes to the managed classes so the entire program could be extended easier in the future and made more simple for someone to use (the original program was very linear and very tightly integrated that the user was required to be a programmer to use it). Using Microsoft’s Common Language Infrastructure (CLI) as a bridge between native C++ and managed C#, it is possible to make the two play together nicely. I’m going to assume that you have a basic knowledge of Microsoft Visual Studio 2008 and basic C#/C++/CLR coding skills.

If you want to follow along, the complete code for the demo program is available at:

http://phamous-apps.com/wordpress/NativeCallbackDemo.zip

I first create a new C++/CLR Class Library and a new C# Windows Form application in Visual Studio:

My solution looks like the following image. CEventTest is the CLI bridge between native and managed classes while NativeClass is a class written in pure C++. I keep all the code in the header file so there is nothing in the CPP file except for a #include for the associated header file so the compiler will compile the program.

The C# project (EventTest) is just a windows form with a multi-line textbox and some buttons like the following image.

In NativeClass.h, I have the following code:

#pragma once

#include
using namespace std;

typedef void (__stdcall *CallbackType)(unsigned char*, int);

class NativeClass
{
public:

    NativeClass(void);
    ~NativeClass(void);

    void CreateByteArray(CallbackType callback)
    {
        int size = 64;
        int byteSize = size * sizeof(float);

        unsigned char* byteArray = new unsigned char[byteSize];
        float* myFloatArray = new float[size];

        for(int i=0; i<size; i++)
        {
            myFloatArray[i] = (float)i * 2;
        }

        memcpy(byteArray, myFloatArray, byteSize);

        callback(byteArray, byteSize);
    }
};

Ok, this seems like very advanced code, but keep calm and I’ll explain what’s going on. The line:

typedef void (__stdcall *CallbackType)(unsigned char*, int);

declares the callback function prototype. CallbackType is a type that I made up. You can call it FooBarType if you want. The next part is the parameter list of the function that is going to be passed. The function I’m sending will have a byte array (unsigned char pointer) and an integer (to define the size of the array). The rest is standard boilerplate code for a function pointer. Just accept that it is magic and change the parts that I mentioned.

The rest of the file is a standard C++ class. The function CreateByteArray takes in the function pointer, so “callback” contains the pointer to the function. We can use “callback” like any other function now. The rest of the code of this function creates a byte array and fills the array with sequential float values. At the end of the function I use “callback” like a normal function. So, that’s one step and the native code is done for now.

Let’s turn to the CEventTest class now. CEventTest will bridge the native code with the managed code. The code is as follows (the comments will explain the code):

// CEventTest.h

#pragma once

#include
using namespace std;

#include "NativeClass.h"

namespace CEventTest {

	// must be outside of class so other classes can use them
	public delegate void NumberSender(int x);

	// delegate used for native C++ callback function
	public delegate void NativeDelegate(unsigned char* buffer, int bufferSize);

	public ref class Processor
	{
	private:
        // native C++ class to use. it must be a pointer.
        static NativeClass* nativeC;

        // must be declared outside of method or else garbage collector will delete!
        static NativeDelegate^ callback;

	public:

		/*
		events must be static in order to be accessed by thread
		and is public so other class can register the event handler
		*/
		static event NumberSender^ SendNumber;

		/*
		This function starts the C++ native class and passes our managed method to it as a callback funtion.
		*/
		static void StartNative()
		{
			using System::IntPtr;
			using System::Runtime::InteropServices::Marshal;

			// get a pointer to the delegate
			IntPtr cbPtr = Marshal::GetFunctionPointerForDelegate(callback);

			// call the native C++ function with our delegate pointer
			nativeC->CreateByteArray(static_cast(cbPtr.ToPointer()));
		}

		// constructor
		Processor()
		{
			nativeC = new NativeClass();

			// cast our managed method to a delegate
			callback = gcnew NativeDelegate(&Processor::NativeByteReceiver);
		}

		// destructor
		~Processor()
		{
			delete nativeC;
		}

		/*
		Our managed method which is to be used as native C++ callback function
		*/

		static void NativeByteReceiver(unsigned char* byteArray, int byteSize)
		{
			int size = byteSize / sizeof(float);

			float* myFloatArray = new float[size];

			memcpy(myFloatArray, byteArray, byteSize);

			for(int i=0; i<size; i++)
			{
				// signal an event
				SendNumber((int)myFloatArray[i]);
			}
		}

		void RunNativeDemo()
		{
			StartNative();
		}
   };
}

Delegates are the equivalent of callback functions in CLI. They must be declared outside of the class like the callback function declaration in C++. I’ve declared two delegates here:

public delegate void NumberSender(int x);
public delegate void NativeDelegate(unsigned char* buffer, int bufferSize);

The first delegate “NumberSender” is used to send an integer value to managed code (ie- the C# class). The other delegate “NativeDelegate” is used to magically take the managed C++ function and get a function pointer for the native C++ class. Remember the managed function and the delegate must have the same argument list (an unsigned char pointer and an integer).

In the class, the native C++ code must be in an object so a pointer can be used. Just accept that it has to be a pointer in order for it to work so that is why it is a static pointer:

// native C++ class to use. it must be a native pointer.
static NativeClass* nativeC;

I also have a public event so that the event can be registered with managed classes:

// managed CLI pointer for the event
static event NumberSender^ SendNumber;

The function for starting the native code has to be static. We need to use the IntPtr type and the Marshal class to get the pointer. A new NativeDelegate is created and is told the function in this class to use. Pass the memory address to the delegate constructor. Then a memory pointer is derived via marshalling. Then we call the function in the native class like normal, but we need to cast the delegate pointer to the callback function type that was declared in native class. Just change the following code to suit your needs.

/*
This function starts the C++ native class and passes our managed
method to it as a callback funtion.
*/

static void StartNative()
{
    using System::IntPtr;
    using System::Runtime::InteropServices::Marshal;

    // cast our managed method to a delegate
    NativeDelegate^ callback = gcnew NativeDelegate(&Processor::NativeByteReceiver);

    // get a pointer to the delegate
    IntPtr cbPtr = Marshal::GetFunctionPointerForDelegate(callback);

    // call the native C++ function with our delegate pointer
    nativeC->CreateByteArray(static_cast(cbPtr.ToPointer()));
}

When the function is called in the native code, the order of events shift back to the CLR class:

/*
Our managed method which is to be used as native C++ callback function
*/

static void NativeByteReceiver(unsigned char* byteArray, int byteSize)
{
    int size = byteSize / sizeof(float);

    float* myFloatArray = new float[size];

    memcpy(myFloatArray, byteArray, byteSize);

    for(int i=0; i<size; i++)
    {
        // signal an event
        SendNumber((int)myFloatArray[i]);
     }
}

It does the reverse of the native class function where it takes the byte array and puts the data into a float array. Each value in the float array is then sent to the C# code via the SendNumber event.

The last function in the class (“RunNativeDemo”) just starts the entire process.

Go to the EventTest project in the Solution Explorer, right click on the project name, and click “Add Reference”. Find the project CEventTest and add the reference. Now the CLR library can be used by the C# windows form project!

In the C# designer view, double-click on the “Native Demo” button and it will generate the method stub. Create the object for the CLR class library (I name the class “Processor” and the object “countThread”). Inside the button’s method stub, I just called the function that runs the native code via CLR.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

// remember to include the reference to the CLR class library
using CEventTest;

namespace EventTest
{
	public partial class Form1 : Form
	{
		// declare the CLR object
		private Processor countThread;

		public Form1()
		{
			InitializeComponent();

			// initialize the CLR object
			countThread = new Processor();

			// link the event for the number sending to a function in this class
			Processor.SendNumber += new NumberSender(Processor_SendNumber);
		}

		/// <summary>
		/// Given an integer, display the number in the textbox
		/// </summary>
		///The integer value sent from the caller
		void Processor_SendNumber(int x)
		{
			// Invoking is required for accessing GUI components
			if (this.InvokeRequired)
			{
				Invoke(new NumberSender(Processor_SendNumber), new object[] { x });
			}
			else
			{
				// Create a string with the number to display in the textbox
				textBox1.AppendText(string.Format("Received Value: {0}\r\n", x));
			}
		}

		/// <summary>
		/// Starts the process to run native code
		/// </summary>
		private void uxNative_Click(object sender, EventArgs e)
		{
			countThread.RunNativeDemo();
		}
	}
}

The callback function in the form requires invoking the delegate. The subject matter is somewhat advanced to explain here so if you want to know more then read up on MSDN and Google. We’ll just accept it as magic here. As long as you have the if-else statement like the above code, swap out the delegate for your own delegate, put your argument list in the object array, and put the GUI-related code in the else block, then you are fine.

Compile the project and run. If everything is working correctly, when the “Native Demo” button is pressed, it should show a list of numbers in the textbox.

There we go! It’s magic! I’m sorry if I skipped a lot of conceptual details because I know I did but I just wanted to throw some code out there for those who want to see the concept in action. It seems there are a lot of write-ups out on the web that explain the theory and have a very basic example, but nothing to show a practical use of the concept.

I also want to note that even though my example uses a byte array, you can use any type you want for the callbacks. Floats, integers, doubles, arrays, etc. I just chose to use a byte array because that is what my project required. I could have just sent the original float array as-is if I wanted to. All I would have to do is change the type to float* instead of unsigned char* and remove the mempy step.

Also it may seem a bit much too just return a byte array from native C++ to C# in this way, but the original code in my project had the callback in a C++ thread (to separate it from the C# GUI thread), which would have complicated the example. I did not want to confuse you so the threading code was removed.

Hopefully this tutorial helped someone and didn’t bore anyone to sleep. For further reading, these links were the ones I used to piece this project together:

http://stackoverflow.com/questions/6507705/callbacks-from-c-back-to-c-sharp

http://stackoverflow.com/questions/2298242/callback-functions-in-c

http://forums.asp.net/t/571841.aspx

Enumeration and arrays

Recently, I discovered the usefulness of the enum type in C++. I can’t believe how long I’ve gone without using an enum because I didn’t know why I should use it over a #define. The two main reasons to use enums over #define is 1) sequential self-numbering and 2) enums allow the value to be visible to the debugger. This post is about the first reason.

Let’s say we want a list of variables, and the variables need to be assigned a unique number for processing, but we don’t care what number is assigned to it. Enumeration to the rescue! Define an enum with a list of variables and it will assign each variable an integer value starting from zero. For example:

enum
{
    alpha,
    beta,
    delta,
    gamma
};

// The values stored in the enum variables are:
// alpha == 0
// beta == 1
// delta == 2
// gamma == 3

Now you can add another variable to the the list in any position (because remember we don’t care what number is assigned to it, it just has to be a unique number) and you won’t have to renumber the other values. It just does it automatically!

enum
{
    alpha,
    beta,
    omega, //<---------
    delta,
    gamma
};

// The values stored in the enum variables are:
// alpha == 0
// beta == 1
// omega == 2
// delta == 3
// gamma == 4

You’re probably thinking: “Great, it self-numbers. What’s the point?” Well the point is that you can use this as array indices and declarations. Assume you have some boolean option settings for your program with the following options: isFullScreen, isWidescreen, isMoving.

Let’s start out making a new file called “options.h” with the following code:

namespace options
{
    enum
    {
        isFullScreen,
        isWidescreen,
        isMoving,
        size
    };
}

I put the enum inside a namespace so that I can use the enum in multiple places without creating an instance of an object. The namespace also allows Visual Studio to list all the enum variables in the autocomplete dialog when using the scope operator ("::"). All I need to do is add #include "options.h" to the top of the header files where I want to use this enum. The last variable size is always going to be the size of the array. Now, remember an enum variable is a const integer value which is why we can use it as an array index value. To use this enum in a class I would use the following code snippet:

// include the namespace file
#include "options.h"

// declares the array, but does not initialize the elements
bool myOptions[options::size];

// then I can initialize the values like so:
myOptions[options::isFullScreen] = false;
myOptions[options::isWidescreen] = false;
myOptions[options::isMoving] = false;

...

// usage example
if(myOptions[options::isFullScreen])
{
    // do something
}

That’s fine and dandy, but if we add another option, we would have to add another line to set that option to false on initialization. We’re lazy and are willing to write more code now to prevent having to write more code in the future so let’s add a reset function to the options namespace.

namespace options
{
    enum
    {
        isFullScreen,
        isWidescreen,
        isMoving,
        size
    };

    static void Reset(bool myArray[options::size], bool value);
}

// the following lines of code are in the same file as the namespace
/**
@brief Resets all the options to a specific value
@param myArray  The array of options using the namespace's enum
@param value    The value to assign to all the options
*/
void options::Reset(bool myArray[options::size], bool value)
{
    for(int i=0; i<options::size; i++)
    {
        myArray[i] = value;
    }
}

I put a value as a parameter because I want the flexibility to set all the options to true or false. The static keyword allows us to use the function without declaring an object so we just reference the function like so in the class:

// declares the array, but does not initialize the elements
bool myOptions[options::size];

// resets all the options
options::Reset(myOptions, false);

...

// usage example
if(myOptions[options::isFullScreen])
{
    // do something
}

Now let’s add another option to the enum to detect if a file is loaded:

namespace options
{
    enum
    {
        isLoaded, //<-----------
        isFullScreen,
        isWidescreen,
        isMoving,
        size
    };

    static void Reset(bool myArray[options::size], bool value);
}

The beauty of this is I can add this function without having to renumber or edit the existing code! I just add the new option where I need to use it.

// still works correctly
if(myOptions[options::isFullScreen])
{
    // do something
}

// do this for the new option
if(myOptions[options::isLoaded])
{
    // do something
}

This is not the only example for using enums with arrays. There are so many possibilities such as having an array of strings and looping through it to read the values. Learning how to use enums for arrays changed my life. It has made me more productive and made maintenance so much easier. It’s such an elegant, cheap, and easy way to improve the code tenfold.

Crypto++ and Linux

This week I’ve re-acquainted myself with Linux at work in order to port an app from Windows to Linux. Besides the aggravation of setting up the OS, IDE, and workflow, I had to use a 3rd party library called Crypto++. Well, it wasn’t obvious to set up or figure out so I’d put this out there in case someone has the same problem.

Basically I was able to include the files, but I got a linker error despite including the files in the project file in Qt. This is the error:

g++ -o encrypter -L/usr/lib -Lcryptopp -lcrypto++ -lQtGui -lQtCore -lpthread
encrypter.o: In function `CryptoPP::AllocatorWithCleanup::allocate(unsigned int, void const*)':
encrypter.cpp:(.text._ZN8CryptoPP20AllocatorWithCleanupIhLb1EE8allocateEjPKv[CryptoPP::AllocatorWithCleanup::allocate(unsigned int, void const*)]+0x2b): undefined reference to `CryptoPP::AlignedAllocate(unsigned int)'
encrypter.cpp:(.text._ZN8CryptoPP20AllocatorWithCleanupIhLb1EE8allocateEjPKv[CryptoPP::AllocatorWithCleanup::allocate(unsigned int, void const*)]+0x38): undefined reference to `CryptoPP::UnalignedAllocate(unsigned int)'
encrypter.o: In function `CryptoPP::AllocatorWithCleanup::deallocate(void*, unsigned int)':
encrypter.cpp:(.text._ZN8CryptoPP20AllocatorWithCleanupIhLb1EE10deallocateEPvj[CryptoPP::AllocatorWithCleanup::deallocate(void*, unsigned int)]+0x25): undefined reference to `CryptoPP::AlignedDeallocate(void*)'
encrypter.cpp:(.text._ZN8CryptoPP20AllocatorWithCleanupIhLb1EE10deallocateEPvj[CryptoPP::AllocatorWithCleanup::deallocate(void*, unsigned int)]+0x32): undefined reference to `CryptoPP::UnalignedDeallocate(void*)'
collect2: ld returned 1 exit status
make: Leaving directory `/home/alex/projects/encrypter'
make: *** [encrypter] Error 1
Exited with code 2.
Error while building project encrypter
When executing build step 'Make'

The proper way to include crypto++ is NOT to download it from the website. Use terminal to get the library:

sudo apt-get install libcrypto++8 libcrypto++8-dbg libcrypto++-dev

Then check if installed on system:

apt-cache pkgnames | grep -i crypto++

Which should result with:

libcrypto++-utils
libcrypto++8
libcrypto++8-dbg
libcrypto++-dev
libcrypto++-doc

If the information above is different (which is possible if it becomes out of date), check the Crypto++ Linux wiki for instructions.

Now add the library to project with the following linkage (written as a makefile macro, but just put the -L and -I parts in the command line if you’re compiling manually):

LIBS += -L/usr/lib/crypto++ -lcrypto++
INCS += -I/usr/include/crypto++

While is is rather specific, someone out there is probably searching for this so here ya go!

If Linux was a car

Really? But your car still runs with Windows

Linux enthusiasts are scary

Shameless cross-post from my car blog: http://yudrivebad.wordpress.com/

(Recursion!!!!)

If Linux was a car, you’d have to build it from scratch just to go to the store to buy some milk. You’d start by compiling an engine and put it on a chassis. That’s fine and dandy and it’ll get you where you need to guy, but it sure is a pain in the ass to turn with a socket wrench on the rack and pinion. So let’s put in a steering column and steering wheel.

It’s not very comfortable so let’s add some seats. Now you realize there are different flavors of seats. Bench, bucket, velour, cloth, leather, etc. Bench sounds nice which is great for cuddling with a significant other! Oh wait, you use Linux. Scratch that, let’s go with buckets for the sportier feel.

Great, but it’s not that great looking. It needs a body. Those damn Apple cars look so sleek and sexy with their glossy exterior, but we all know you can’t modify them. Fk the sheeple and their pretty cars. Those Windows cars actually look pretty good now unlike a few years ago when the Fisher Price Cozy Coup called them out on plagiarism. What can I do with the Linux car? Well, there’s not much to choose from out of the box. Fkr looks cartoony. Meh, fk it, let’s roll.

It drives just as well as the Apple car because they’re almost identical under the hood. You’re feeling pretty smug because you built your own car for free. Well, let’s keep adding mods. You want lib-vtec-honda, but it won’t work in your car. You hack it to work instead. You’re somewhat successful, but you needed another obscure library to get it to work: lib-jdm-bolts. Ok, it works fine, but not perfect.

Oh no, the radio stopped working! Ok, don’t panic, just use another antenna. Crap, it’s not compatible with Linux and you just paid out the butt for it. To the Googles! So many people have the same issue, but with different hardware. WTF?! Grrrr! Ok, this guy says to download ndis-radio-wifi-2.6.1 and compile it for my specific car. Ok. Fk! I need another obscure library: lib-am-fm-cassette. Don’t I already have that?! Jebus H. Chrysler this is retarded.

Wheee, got the radio working. Let’s roll. Going to Taco Bell for some chalupas and Baja Blast. Oh muffin fudger, it doesn’t have a fkn cupholder. Google it. Cupholders aren’t available to Linux due to it being proprietary technology developed by Adobe?! GD it to hell! You end up burning the car and buying a Windows car.

Android: What does “Volatile” mean?

At work, I’m currently working on a very large project, and a lot of it was previously written by some very experienced programmers, far beyond my level of skill. When I read through it, I often come across weird things I’ve never seen before (a lot of which gives me the content to post here!) One of these I cam across recently was this word:

volatile

Its a strange prefix to a variable name, and the first few times I looked it up, I was not able to find a clear or concise answer. When I try to compile it into simple programs, it never yielded any visible differences. I have found this article from Javamex which put together a rather simple table and explanation of what it actually does.

Essentially, volatile is used to indicate that a variable’s value will be modified by different threads.

Briefly, I can tell you it is related to threads and synchronization, so if your programs don’t have a lot of multi thread functionality, this keyword *probably doesn’t affect you. Check out the article here and feel free to toss in any comments to shed light some more light for our readers!

-Kevin Grant

Android: Getting screen pixel size and dimensions

In one of our programs, I hackishly figured out how to get screen size based off of measuring a view in the onDraw() method and only doing it the first onDraw, and blah yada blah etc. This was terrible and I knew it from the beginning, but it works, so whatever. However, I have run into the same problem into a different project and that method won’t work here, so I researched it again. Low and behold, it was much easier that I ever thought (just like everything else).

DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

and now you can access everything you want through this “metrics” variable. Found this right on the android site under Display Metrics

-Kevin Grant

Android: Ain’t no Callerback grl… (Callback functions in Android)

When I learned about callback functions in Android, it literally created a whole new world of possibilities of what I could do withing my apps. For so long I had used callback functions without even knowing it! An example of a callback function we all already use is with buttons and the onClickListener(). Usually when you create a button, you register a listener, and then you put code into it, like so:

Button btn = (Button) findViewById(yada_yada_yada);
btn.setOnclickListener(new OnClickListener(){
	@Override
	public void onClick(View v){
		// do something
	}
});

Basically, whenever you press a button, it sends a callback to this listener you set, and your program can do whatever you want in here. What we want to do now is replicate this sort of callback, but not for a button press. We want to replicate this for ANYTHING! In the example code I provide, we can now do things like this:

rst = new RandomSenderThingy();
rst.setRandomThingyListener(new RandomSenderThingyListener(){
	@Override
	public void onBoolThingChanged(boolean changed) {
		Log.d("DEBUG","Callback Received! It is: " + changed);
	}
});

The example code makes use of a few various techniques to get the point across, but I’ve clearly commented the parts that you will need to inject into your own code to get this functionality. Good luck and post any questions or comments in the comments section!

Download the source code here

-Kevin Grant

Android: Debug certificate expired

Have you received this error?

Error generating final archive: Debug Certificate expired on 2/9/2011 11:55 PM

I just got it today! The fix is quite simple, just locate your debug.keystore file, delete it, and and then select “clean all projects” in eclipse. I followed this brief tutorial from a guy over at “The Java Dude”.

Check out his tutorial here

-Kevin Grant

Writing and getting variables from Windows registry

MFC makes it easy to use the Windows Registry to store your application’s settings and variables. This allows your application to retain last used options, recent files, preferences, colors, fields, whatever. I’m assuming that you can use Visual Studio’s new project wizard to make a new MFC application/project.

I am using Visual Studio 2008 SP1 on Windows Vista 32-bit as of the writing of this article.

In the main cpp file that is generated, find the InitInstance() function. In this function, there should be a function call to SetRegistryKey. This function takes in a LPCTSTR (which is a long pointer to string) and you can just give it any string (Microsoft recommends using the company name here). I would use it like this:

SetRegistryKey(_T("My Fookin Company"));

The “_T()” part is just a macro that converts the string to a LPCTSTR. This line is all you need to set your program to use the registry. If it isn’t in InitInstance(), then just add it.

To save information to the registry, you would use the following code:

// get the current application object
CWinApp* pApp = AfxGetApp();

// This is the string I want to save
CString engrName = "Alex";
int age = 24;

// "ArbitrarySectionName" is the collection of information to store (if you have multiple sections in your application such as "userProfile" and "userSettings" then you would use those different names)
// _T("engrName") is a variable in the registry. you create this here so you can name it "foobar" for all it cares
// just remember what you named it so you can get it later
// engrName (the last parameter) is what you're saving (in this case, it is the string "Alex")
pApp->WriteProfileString(_T("ArbitrarySectionName"), _T("engrName"), engrName );

// let's just save an integer for the hell of it
pApp->WriteProfileInt(_T("ArbitrarySectionName"), _T("engrAge"), age);

// not using pointer anymore
pApp = NULL;

To get information from the registry, you would have needed to save information there in the first place. If there is nothing there, you would get blank information. To get the information from the registry you would use the following code to get it:

// get the current application object
CWinApp* pApp = AfxGetApp();

// get string from registry and assign to a string
// GetProfileString returns a CString object
// GetProfileInt returns an integer
// "ArbitrarySectionName" is where the collection of information is stored (you set this on save)
// "engrName" and "engrAge" are the variables in the section "ArbitrarySectionName" where you saved single pieces of data
CString strVar = pApp->GetProfileString(_T("ArbitrarySectionName"), _T("engrName") ) );
int intVar = pApp->GetProfileInt(_T("ArbitrarySectionName"), _T("engrAge") ) );

// not using pointer anymore
pApp = NULL;

You can use both pieces of code anywhere in your MFC classes. Just note there are only functions for integers and strings. None for decimal numbers, unfortunately. For more information, here are some links to MSDN:

SetRegistryKey()
WriteProfileInt()
GetProfileInt()
WriteProfileString()
GetProfileString()
Article that I used to figure out how to use the registry