Click here to Skip to main content
15,896,154 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I am creating a library project which can be used in both a normal program and used in a dll file in both windows and linux, for that reason i want to hardcode some error strings for use in case of various error messages.


The problem: I know there are 2 ways in which it can be done.

1. Create a file called errordesc.h and create a constant string for each error.
2. The use of a resource script file with a stringtable.

My question however is wheather a resource script file is supported in linux programs? because if the use of a resource script file is not supported in linux programs, then I will have to use an .h file unless there is other solutions.
Posted
Updated 30-Sep-12 2:11am
v2

Have a look at ICU Resource Management[^]

ICU does this pretty well on various operating systems.

Best regards
Espen Harlinn
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 30-Sep-12 13:31pm    
Very interesting approach, good to know. My 5, and thank you for sharing.
--SA
Espen Harlinn 30-Sep-12 17:54pm    
Thank you, Sergey :-D
As far as I know, you cannot use Windows resource scripts on Linux, so I would use a header file.
 
Share this answer
 
In case of crossplatform projects the .rc file is a big no-no when you can put the data elsewhere. Normally it should contain only the necessary windows specific stuff, maybe a versioninfo, a manifest and an icon...

The question is: do you plan localization later? If not then hardcode the text in plain english into your source code. (You can of course collect them to a centralized place...) If you want localization then instead of the string or an int ID use a descriptive key string from the code that needs the right string for the current language. OK, what is the right place for the strings of a language??? Its definitely not a stringtable resource in my opinion!

The resource string table is one of the least useful things in the world. :-) I guess it exists just because we inherited it from ancient times. Many programs used that for example in DLLs to provide localization data, they put the translated text for each language into a different dll and they loaded a different dll depending on the language. My question is: whyz ooooh why to load a DLL just to get strings for a language from it? The problem is that not everything is true you read on the internet, and not every solution is good because it exists. Here is my resoning why is it worth investing a little bit of time to store localization data in another format:

Localization is usually done by an external company specilaizing in translation. Their people are often not computer scientists and they tend to screw up resource script files, and you won't be able to correct it later lets say in case of korean or chinese - to make it worse in case of multiline text its not trivial how to wrap lines, it depends heavily on language so manually correcting these things on your side is often impossible. If something is screwed up then you have to resend the stuff for them and you might have to make unneeded roundtrips that in worst case is able to push even a release date...

Instead of sending them a bare .rc file its much better to provide them some fancy tools, like an excel sheet that contains the languages and the localized keys in the columns and rows. The funny about excel sheets is that you can setup even the font sizes and column sizes so they immediately have a WYSIWYG tool to wrap multiline text. Later you can save the spreadsheet as an utf8 xml and you can get data out of it easily and you can convert it to another xml that doesn't contain excel specific formatting tags or you can save the localization data to separate utf8 text files per language. This is crossplatform and hassle free solution. Writing a loader that loads your custom format is easy and worths every second if correct localization matters. Its a small piece of code that is critical and makes you a lot of headaches later if isn't done correctly.

Even if you use localization support its good practice to put the default language (usually english) into the code as well.
 
Share this answer
 
I thank you all for you help, it was not easy to find the right solution to my problem, but I belive Ihave found the right solution which I would like to share with everybody. Also after reading this MS. article on dllmain reconmendation, and according to the article the C runtime library may not be properly initialized is certain cases so using th C memory allocation functions was out of the question.

MS article 'Best Practices for Creating DLLs' http://msdn.microsoft.com/en-us/library/windows/hardware/gg487379.aspx[^]

My solution:
file 'langdesc.h'
C++
#ifndef LANGDESC_DEFINED
#define LANGDESC_DEFINED

#define TEXT_DEFAULT_ERROR "Unknown error number suplied"
#define TEXT_NO_ERROR      "Info: no errors have been happend"
#define TEXT_INDEX_OUT_OF_BOUNDS "Index out of bounds error"
#define TEXT_LIST_EMPTY = "the list is empty, try adding an item to the list first!"

#endif LANGDESC_DEFINED


file 'errordesc.h'
#ifndef ERRORDESC_DEFINED
#define ERRORDESC_DEFINED

#ifdef __cplusplus
extern "C" {
#endif
	
#ifndef NULL
#define NULL ((void *)0)
#endif /* NULL */

#define ERROR_N0_ERROR       0
#define ERROR_DEFAULT_EROR   1
#define ERROR_INDEX_OUT_OF_BOUNDS     10
#define ERROR_LIST_EMPTY              11

extern int GetErrorDescription(const int number, char *pOut, const int out_size);

#ifdef __cplusplus
}
#endif

#endif /* ERRORDESC_DEFINED */


I came to the conclusion based on certain win32 functions like the RegQueryValueEx where it is posible to query the length of a string simply be setting the lpvalue parameter to NULL, the functions still returns success, but places the actually required size in the lpcbValue parameter, which is handy.

Also I do not use any of the C standards include libraries, so I created made the necessary functions by hand, I may be paranoid, but that's another discussion.

file 'errordesc.c'
C#
/* File : errordesc.c */
#include "errordesc.h"
#include "langdesc.h"


/* Local Functions Declaration Sectio
 *-----------------------------------------------
 */
int copy_text(char *dest, const char *source, const int dest_size);
int text_len(const char *source);

/* External  Functions Section
 *-----------------------------------------------------------------------------
 */
int GetErrorDescription(const int number, char *pOut, const int out_size)
{
    const char *cp;
    int iLen = 0;
    switch (number)
    {
    case ERROR_N0_ERROR:
        cp = TEXT_NO_ERROR;
        break;
    case ERROR_INDEX_OUT_OF_BOUNDS:
        cp = TEXT_INDEX_OUT_OF_BOUNDS;
        break;
    case ERROR_LIST_EMPTY:
        cp = TEXT_LIST_EMPTY;
        break;
    default:
        cp = TEXT_DEFAULT_ERROR;
        break;
    }

    if (pOut == NULL)
    {
        return text_len(cp);
    }
    iLen = copy_text(pOut, cp, out_size);

    return iLen;
}


/* Local  Functions Section
 *-----------------------------------------------------------------------------
 */
int copy_text(char *dest, const char *source, const int dest_size)
{
    int i;
    i = 0;
    if (dest != NULL && source != NULL)
    {
        for (i = 0; i < (dest_size-1); i++)
        {
            if (source[i] == '\0')
            {
                dest[i] = '\0';
                return i;
            }
            dest[i] = source[i];
        }
    }
    dest[dest_size-1] = '\0';
    return i;
}

int text_len(const char *source)
{
    int iLen;

    iLen = 0;
    if (source != NULL)
    {
        while (source[iLen] != '\0')
        {
            iLen++;
        }
    }
    return iLen;
}


How it works?.
-----------------

1. The problem I bump in to was how to define the error codes and the text itself, so I came with the following decalration:

TEXT_<descriptive error="" text=""> these are the actally text definitions
ERROR_<descriptive text=""> the are the error number definitions

#define TEXT_INDEX_OUT_OF_BOUNDS "Index out of bounds error"
#define ERROR_INDEX_OUT_OF_BOUNDS 10

By prefixing all the strings with either TEXT or ERROR it is very easy to in a switch statement.

3. adding a new error text is done in 4 steps:
-----------------------------------------------
step 1:
Add a line below the last define statement in the langspec.h file,
#define TEXT_SOME_ERROR "some error occured"

step 2.
Add another line below the last #define statement in the errordesc.h file,
#define ERROR_SOME_ERROR 20

Step 3.
Add three line below the last case statement in the errordesc.h file
case ERROR_SOME_ERROR:
cp = TEXT_SOME_ERROR;
break;

step 4.
Add ERROR_SOME_ERROR statement in a return statement or added it to a variable to hold the last error, a bit like how the GetLastErrror works.


3. This way these 3 files can be placed in a dll file to make a language file, also the use of the langdesc.h header file also make it fairly easy to change the error text between warious languages, also This little language file can easly be adjusted ti unicode with a couple of macros.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900