Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

typedef XS(foo) - fails in C++ /w 5.10.0

135 views
Skip to first unread message

Patrick Rutkowski

unread,
Jan 7, 2008, 3:51:39 PM1/7/08
to perl5-...@perl.org
Outlined below is a problem I ran into today followed by a suggested fix.

First, some background information. XSUB.h in 5.8.8. defined the macro
XS(name) as such:

===== START CODE =====

    #if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
    #  define XS(name) __declspec(dllexport) void name(pTHX_ CV* cv)
    #else
    #  ifdef HASATTRIBUTE_UNUSED
    #    define XS(name) void name(pTHX_ CV* cv __attribute__unused__)
    #  else
    #    define XS(name) void name(pTHX_ CV* cv)
    #  endif
    #endif

===== END CODE =====


The main version of the definition I’m interested is “#define XS(name) void
name(pTHX_ CV* cv)”.
 
In 5.10.0 these definitions changed to the following:

===== START CODE =====

    /* XSPROTO() is also used by SWIG like this:
     *
     *     typedef XSPROTO(SwigPerlWrapper);
     *     typedef SwigPerlWrapper *SwigPerlWrapperPtr;
     *
     * This code needs to be compilable under both C and C++.
     *
     * Don't forget to change the __attribute__unused__ version of XS()
     * below too if you change XSPROTO() here.
     */
    #define XSPROTO(name) void name(pTHX_ CV* cv)
   
    #undef XS
    #if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)
    #  define XS(name) __declspec(dllexport) XSPROTO(name)
    #endif
    #if defined(__SYMBIAN32__)
    #  define XS(name) EXPORT_C XSPROTO(name)
    #endif
    #ifndef XS
    #  if defined(HASATTRIBUTE_UNUSED) && !defined(__cplusplus)
    #    define XS(name) void name(pTHX_ CV* cv __attribute__unused__)
    #  else
    #    ifdef __cplusplus
    #      define XS(name) extern "C" XSPROTO(name)
    #    else
    #      define XS(name) XSPROTO(name)
    #    endif
    #  endif
    #endif

===== END CODE =====


The main definition I’m interested here is the __cplusplus specific one:
“#define XS(name) extern "C" XSPROTO(name)”.


== THE PROBLEM ==

I have some code (namely XML::Xerces-2.7.0-0’s Xerces.cpp source file) which
does one of these:

    *code*: typedef XS(SwigPerlWrapper);

Now, on 5.8.8 this would evaluate to something the following statement,
which is all well and good:

    *code*: typedef void SwigPerlWrapper(pTHX_ CV* cv);

However, on 5.10.0 it evaluates to:

    *code*: typedef extern “C” void SwigPerlWrapper(pTHX_ CV* cv);

The “extern “C”” part makes the compiler die with the following message:

error: expected unqualified-id before string constant
error: expected `,' or `;' before string constant


== PROPOSED FIX ==

I propose that there be a new macro added called XS_TYPEDEF. This macro
would be defined in the usual way when __cplusplus is not present:

#define XS_TYPEDEF(name) typedef XS(name)

However, when __cplusplus is defined it would be set to something like this:

#define XS_TYPEDEF(name) extern “C” { typedef XS(name); }

What do you guys think?

-Patrick


Jan Dubois

unread,
Jan 7, 2008, 4:19:41 PM1/7/08
to Patrick Rutkowski, perl5-...@perl.org
On Mon, 07 Jan 2008, Patrick Rutkowski wrote:
> I propose that there be a new macro added called XS_TYPEDEF. This macro
> would be defined in the usual way when __cplusplus is not present:
>
> #define XS_TYPEDEF(name) typedef XS(name)
>
> However, when __cplusplus is defined it would be set to something like this:
>
> #define XS_TYPEDEF(name) extern "C" { typedef XS(name); }

I added the XSPROTO() macro exactly for this problem:

http://public.activestate.com/cgi-bin/perlbrowse/p/31697

You will be responsible to put the extern "C" block around your code yourself,
which shouldn't be a problem as you already know your source code is in C++:

extern "C" {
typedef XSPROTO(name);
}

You'll see that a corresponding patch to use XSPROTO() when available has
also been made to the Swig repository:

http://sourceforge.net/tracker/index.php?func=detail&aid=1771410&group_id=1645&atid=301645

It should be in Swig 1.3.33:

http://sourceforge.net/project/showfiles.php?group_id=1645

(it looks like recent releases are no longer listed on the main Swig page).

Cheers,
-Jan


Patrick Rutkowski

unread,
Jan 7, 2008, 2:55:34 PM1/7/08
to perl5-...@perl.org

===== START CODE =====

#if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)

#else

# ifdef HASATTRIBUTE_UNUSED

# else

# endif

#endif

===== END CODE =====

===== START CODE =====

*

* typedef XSPROTO(SwigPerlWrapper);

* typedef SwigPerlWrapper *SwigPerlWrapperPtr;

*

*

*/

#undef XS

#if defined(__CYGWIN__) && defined(USE_DYNAMIC_LOADING)

#endif

#if defined(__SYMBIAN32__)

#endif

#ifndef XS

# else

# ifdef __cplusplus

# else

# define XS(name) XSPROTO(name)

# endif

# endif

#endif

===== END CODE =====

== THE PROBLEM ==

*code*: typedef XS(SwigPerlWrapper);

== PROPOSED FIX ==

I propose that there be a new macro added called XS_TYPEDEF. This macro


would be defined in the usual way when __cplusplus is not present:

#define XS_TYPEDEF(name) typedef XS(name)

However, when __cplusplus is defined it would be set to something like
this:

#define XS_TYPEDEF(name) extern "C" { typedef XS(name); }

What do you guys think?

-Patrick

Patrick Rutkowski

unread,
Jan 7, 2008, 3:50:17 PM1/7/08
to perl5-...@perl.org

Patrick Rutkowski

unread,
Jan 8, 2008, 11:29:58 AM1/8/08
to perl5-...@perl.org
Ah, ok; I didn't know this problem had been hit already.

That solution is fine then. However, I have to mention that using XSPROTO()
means that you loose all of the extra logic provided by XS(). Having an
XS_TYPEDEF() macro which uses XS() internally would let you keep all of
that. Whether or not things like __declspec(), EXTERN_C, or
__attribute__unused__ even do anything in a typedef I don't know; but that's
just my 2 cents.

-Patrick

0 new messages