Library design nastiness

B

Boon

Hello everyone,

I'm trying to use a closed-source library which requires me to define the
following function.

INT InitSem(t_Sem *pSem, UINT32 uiValue);

where

typedef int INT ;
typedef unsigned long UINT32 ;

(I'm not sure what these typedefs buys the library authors, nor what happens
when unsigned long is wider than 32 bits.)

and

typedef unsigned long DWORD ;
typedef DWORD t_Sem[SEM_SIZE_IN_DWORD];

I'm supposed to "tell" the library how big a t_Sem object is by providing an
appropriate definition for SEM_SIZE_IN_DWORD.

However, the actual object is not an array of DWORDs but a struct :

struct REAL_SEM
{
stuff in there;
}

but the library does not want to know the details of the real object, and so it
treats it as an array of SEM_SIZE_IN_DWORD DWORDs.

This means I have to write InitSem like this :

INT InitSem(t_Sem *pSem, UINT32 uiValue)
{
struct REAL_SEM *p = (struct REAL_SEM *)pSem;
/* use p */
return 0;
}

I'm not sure it is "safe" to cast a "pointer to DWORD array" into a "pointer to
struct" is it? What could possibly go wrong?

Regards.
 
J

James Kuyper

Boon said:
Hello everyone,

I'm trying to use a closed-source library which requires me to define
the following function.

INT InitSem(t_Sem *pSem, UINT32 uiValue);

where

typedef int INT ;
typedef unsigned long UINT32 ;

(I'm not sure what these typedefs buys the library authors, nor what
happens when unsigned long is wider than 32 bits.)

and

typedef unsigned long DWORD ;
typedef DWORD t_Sem[SEM_SIZE_IN_DWORD];

I'm supposed to "tell" the library how big a t_Sem object is by
providing an appropriate definition for SEM_SIZE_IN_DWORD.

However, the actual object is not an array of DWORDs but a struct :

struct REAL_SEM
{
stuff in there;
}

but the library does not want to know the details of the real object,
and so it treats it as an array of SEM_SIZE_IN_DWORD DWORDs.

This means I have to write InitSem like this :

INT InitSem(t_Sem *pSem, UINT32 uiValue)
{
struct REAL_SEM *p = (struct REAL_SEM *)pSem;
/* use p */
return 0;
}

I'm not sure it is "safe" to cast a "pointer to DWORD array" into a
"pointer to struct" is it? What could possibly go wrong?

For one thing, DWORD and struct REAL_SEM might have different alignment
requirements. Even if alignment isn't an issue, if any piece of code can
access the structure through pSem and simultaneously by an lvalue of
type struct REAL_SEM, the compiler is not required to consider the
possibility that the two different ways of accessing it might refer to
the same object, which means that, for instance, changes done using one
method might not be reflected when it is read by the other method.

The safest way to avoid such problems would be as follows

#define SEM_SIZE_IN_DWORD \
((sizeof(struct REAL_SEM)+sizeof(DWORD)-1)/sizeof(DWORD))

/* The complicated numerator is intended to ensure that the size rounds
* upward, in the event that sizeof(struct REAL_SEM) is not an integer
* multiple of sizeof(DWORD).
*/

INT InitSem(t_Sem *pSem, UINT32 uiValue)
{
struct REAL_SEM rs;
memcpy(&rs, psem, sizeof rs);
/* use rs */

if(you modified rs)
memcpy(psem, &rs, sizeof rs);

return 0;
}
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top