Compiling Sage 300 Views with C++

As you are probably aware, Sage 300 views can be compiled with a C++ compiler. You have probably noticed the:

#if defined(__cplusplus)

namespace A4WAPI {

#endif

wrappers in the program files and

#ifdef __cplusplus

extern "C" {

#endif

in the header files, but if you are like me, have never had a need to compile a view with C++, so never thought much about it. I’m certainly not recommending that you do compile your views with the C++ compiler, but if you really need to, it is possible. In my case, I needed to include a specific C++ library as I couldn’t find a C library that did the job as well. So, it was a choice of compiling in C++ or rewriting around 40k lines of C++ code in C.

Needless to say, I chose compiling in C++, but having made that decision I was unable to find any documentation on how to do it. Feeling adventurous, I just renamed the .c files to .cpp and tried compiling. It didn’t work. I got a couple of “array bounds overflow” errors caused by the ‘blank padded table name’ (due to C++’s insistence on adding a null terminator to every string – making the table name 9 characters instead of 8) and a bunch of other errors in my code.

Having asked dppsupport for any documentation on how to do it, I was pointed in the direction of the CPPVIEW view template which I had never noticed before. Thinking I would have to re-instantiate the view code, I dived into the \PLUSWDEV\TEMPLATE\CPPVIEW folder to check out the code for a C++ view, but was surprised to find that there really wasn’t any. Looking in the ‘files’ file I could see why. All the files were pointing to ..\CVIEW\. The only difference was that the .c files were renamed .cpp. The only actual file in \CPPVIEW was the .mak file and the only change in that file was to update the two .c filenames in the dependencies to .cpp.

Looking in the sample phone.ptn file that was in the \CPPVIEW folder, there was one important change. The blank padded table name had been changed from a string to an array of chars. Yes, in C a string IS an array of characters – but in C++ there is a difference. This change was obviously to work around the “array bounds overflow” errors I had encountered earlier.

So, instead of:

pppp="TUPHONE "    ; table name - padded to eight characters

it had been changed to:

pppp={'T','U','P','H','O','N','E',' '}     ; table name - padded to eight characters

Making the same change in my existing view resolved the “array bounds overflow” errors.

So, rather than re-instantiating your views, you can compile with C++ by just making a few small changes:

  1. Rename the two .c files to .cpp (there is no need to rename the .h files to .hpp).
  2. Update the two .c file names to .cpp in the .mak file dependencies.
  3. Change the blank padded table name to an array of chars. You do this once in the 1.c file and once in the .c file. Just search for your blank padded table name eg: "TUPHONE " and change it to eg: {'T','U','P','H','O','N','E',' '} or look in the template code to see where pppp is used.
  4. Also, if you are using VEXTRA in your 1.h file, move all its members to the VEXTRA struct in 3.h and comment out DO_VIEWHANDLE in 1.h. Then change all the “lpv->extra.”s to just “lpv->“ in your code wherever those members are referenced.

That’s it. Just compile the view as per normal, and all the standard view template code will compile nicely with the C++ compiler.

However…

Whilst Sage have made sure all their code works nicely with the C++ compiler, the same can’t be said for your own code. There are a few differences between C and C++ which will probably mean having to update your code before it will compile. Unfortunately, in my case I was converting a view with a viewProcess which was over 12,000 lines of code. Normally though’ it shouldn’t take too long to make the required changes.

There are some new reserved words in C++ that aren’t in C, but I didn’t come across this problem. I would say it would be pretty unlikely, but if you do have a variable or something that is a C++ reserved word, you will just have to change it.

I did get a few “array bounds overflow” errors in my own code, but these are easily fixed by providing room for the extra null terminator if possible (eg: just adding 1 char to the length of a buffer) or using the same ‘array of chars’ method used to fix the table names above.

Most of the errors you get though will probably be due to C++’s stronger typing than C. You pretty much have to cast everything as there is no implicit casting. For example, the line:

LPRATEINFO lpRateInfo = memAlloc (sizeof (RATEINFO));

will give the error:

error C2440: 'initializing' : cannot convert from 'LPVOID' to 'A4WAPI::LPRATEINFO'

Conversion from 'void*' to pointer to non-'void' requires an explicit cast

So, you will need to change the line to:

LPRATEINFO lpRateInfo = (LPRATEINFO)memAlloc (sizeof (RATEINFO));

Similarly, all the newer view routines like viewFilterDelete, viewRecordClear, viewFilterSelect etc. all have the first view handle defined as LPRVH rather than LPVOID, so a line like:

viewFilterDelete (DMLINE->rvh, DMLINE->view, szStatement, 0);

will need to be changed to:

viewFilterDelete ((LPRVH)DMLINE->rvh, DMLINE->view, szStatement, 0);

Basically, any implicit casting in your C code will need to be explicitly cast in C++.

Anyway, by working my way through the compiler errors and googling error numbers where necessary, I was able to get my view compiling as C++ relatively quickly. I then included the C++ library I wanted to use and the whole thing compiled and ran smoothly. So, whilst this is by no means an official guide to compiling Sage 300 views with C++, hopefully you can learn from my experience.

Happy Coding!

John Paterson, CEO at Dingosoft
Visit my blog and find Dingosoft on Social Media:

Anonymous