OK, this post is mostly a reminder to myself, but maybe it’ll help others as well.

Today I was recompiling my experimental “FlowField” particle system force plugin for Max 2013 and made several changes that were required to get it to compile for the Max 2013 SDK, but the linker stage failed with quite a few errors.  It had been a while since I converted a project to build for Max 2013 and I didn’t remember all the details about what would cause this problem.

Turns out that I had forgotten to set up Unicode for the project.  In Configuration Properties|General|Character Set, you need to select Use Unicode Character Set.  And of course, once you do that, if you’re doing any string manipulation in your code, you’ll need to alter that as well to use unicode-compatible data and functions.

The trick is, once you make these changes in the code it builds fine under the Max 2013 SDK, but what if you want to also build a version for Max 2012, 2011 or earlier?  The code will break when compiled with the new definitions.

There are a number of things that the compiler will barf on when converting projects to unicode, so I throw this block of code into my main header for projects:

// This is set up for things that are const in Max 2013 and later

#ifdef MAX_RELEASE_R15
#define MAX2013CONST const
#define gen_snprintf swprintf
#define gen_strcat wcscat
#define gen_strlen wcslen
#define gen_strcpy wcscpy
#define MAX2013CONST
#define p_end end
#define gen_snprintf _snprintf
#define gen_strcat strcat
#define gen_strlen strlen
#define gen_strcpy strcpy

Several code-consistency problems have been cleaned up in the Max 2013 SDK, with some functions returning “const” values, so I have defined the MAX2013CONST macro for these methods, such as GetObjectName — The same code will build on earlier SDK releases using this macro, which is null for earlier releases.

Literal strings need to be defined in such a way that they will generate proper data when built for normal strings and unicode.  To do this, they should be wrapped in a TEXT() macro:

TEXT(“This is a text string”);

This macro generates simple one-byte strings when built in a non-unicode environment and generates two-byte unicode strings when building for unicode.

I was getting compiler failures on “p_end” tags in parameter blocks when building with earlier SDKs so for pre-Max-2013 builds, I define the P_end macro.

Finally, string manipulation needs to be done with the appropriate functions, which differ when using legacy char strings and unicode strings, so I set up “gen_xxx” string manipulation macros, which resolve to the proper code ad compile time.

The bottom line is, the same code builds properly for all versions of Max.

Now if I can just remember to look here in the future…