From ripley at stats.ox.ac.uk  Tue Mar 20 08:12:25 2007
From: ripley at stats.ox.ac.uk (Prof Brian Ripley)
Date: Tue, 20 Mar 2007 07:12:25 +0000 (GMT)
Subject: [Rd] Rinternals.h and undefined symbols
In-Reply-To: <45FF321C.2020400@stats.uwo.ca>
References: <9001E5A6-9080-4224-92ED-4867C858C637@ic.ac.uk>
	<45FF016B.3060505@stats.uwo.ca>
	<4E0FCC76-D2E2-40E3-A2F7-C15519D286C1@ic.ac.uk>
	<45FF2866.7060705@stats.uwo.ca>
	<B97996F0-05E3-424E-B79F-BA9C9EE125FE@ic.ac.uk>
	<45FF2FD4.1080601@stats.uwo.ca>
	<BE02BC30-532E-4398-AF56-BA5B76DDD308@ic.ac.uk>
	<45FF321C.2020400@stats.uwo.ca>
Message-ID: <Pine.LNX.4.64.0703200707430.6222@gannet.stats.ox.ac.uk>

Note though that you should include C header files inside extern "C" in 
your C++ code.  'Writing R Extensions' says

   Some @R{} header files are C and not C++ header files and should be
   included within an @code{extern "C"} block: for clarity this is
   advisable for all @R{} header files.

On Mon, 19 Mar 2007, Duncan Murdoch wrote:

> On 3/19/2007 8:55 PM, Ernest Turro wrote:
>> On 20 Mar 2007, at 00:50, Duncan Murdoch wrote:
>>
>>> On 3/19/2007 8:41 PM, Ernest Turro wrote:
>>>> On 20 Mar 2007, at 00:18, Duncan Murdoch wrote:
>>>>> On 3/19/2007 7:41 PM, Ernest Turro wrote:
>>>>>> On 19 Mar 2007, at 21:32, Duncan Murdoch wrote:
>>>>>>> On 3/19/2007 5:23 PM, Ernest Turro wrote:
>>>>>>>> Hi,
>>>>>>>> I'm trying to register my native routines using
>>>>>>>> R_registerRoutines  (...). I can compile the code, but the
>>>>>>>> loader cannot resolve the  symbol:
>>>>>>>> undefined symbol:
>>>>>>>> _Z18R_registerRoutinesP8_DllInfoPK12R_CMethodDefPK15R_CallMethodD
>>>>>>>> ef S3 _S6 _
>>>>>>>> $ nm bgx.Rcheck/bgx/libs/bgx.so | grep R_registerRoutines
>>>>>>>>                   U
>>>>>>>> _Z18R_registerRoutinesP8_DllInfoPK12R_CMethodDefPK15R_CallMethodD
>>>>>>>> ef S3 _S6 _
>>>>>>>> Why does it have this funny name? If I look at libR.so, I get
>>>>>>>> an   ordinary symbol name:
>>>>>>> That looks like C++ name mangling.  Are you wrapping your
>>>>>>> declarations in
>>>>>>>
>>>>>>> extern "C" { }
>>>>>>>
>>>>>>> ?
>>>>>> Yeah, the routine is literally just:
>>>>>> extern "C"
>>>>>>    void R_init_bgx(DllInfo *info) {
>>>>>>      R_registerRoutines(info, cMethods,NULL,NULL,NULL);
>>>>>>    }
>>>>>> with cMethods declared outside as a static const R_CMethodDef.
>>>>> I'm no C++ expert, but that looks like it declares R_init_bgx to
>>>>> be  a "C" routine, but not R_registerRoutines (which is what the
>>>>> error  was about).  Its declaration is in Rdynload.h:
>>>>>
>>>>> #ifdef __cplusplus
>>>>> extern "C" {
>>>>> #endif
>>>>> int R_registerRoutines(DllInfo *info, const R_CMethodDef * const
>>>>> croutines,
>>>>> 		       const R_CallMethodDef * const callRoutines,
>>>>> 		       const R_FortranMethodDef * const fortranRoutines,
>>>>>                        const R_ExternalMethodDef * const
>>>>> externalRoutines);
>>>>>
>>>>> Rboolean R_useDynamicSymbols(DllInfo *info, Rboolean value);
>>>>> #ifdef __cplusplus
>>>>> }
>>>>> #endif
>>>>>
>>>>> so maybe your compiler doesn't define __cplusplus, or you didn't
>>>>> include R_ext/Rdynload.h?
>>
>>
>> Duncan, you hit the nail on the head. Thanks so much.
>>
>> If you download R-2.4.1.tar.gz from CRAN you will find that the
>> extern "C" is missing in Rdynload.h! I added it to my copy and my
>> code compiles now. I wonder why it's missing. Has this been fixed in
>> cvs?
>
> Yes, it's a new addition Duncan Temple Lang added in November.  I didn't
> remember that or I would have mentioned it.
>
> Duncan Murdoch
>
>> Thanks,
>>
>> Ernest
>>
>> PS. you don't need the braces after extern "C"
>>
>>
>>
>>>> Thanks for the reply.
>>>> __cplusplus is defined and I do #include <R_ext/Rdynload.h>
>>>> (after  all, it does compile)...
>>>> I've tried this on two different machines, so it's not a problem
>>>> specific to my setup either...  ):
>>> Here I'm just guessing:  you don't wrap the whole function in
>>> extern "C", you just put extern "C" ahead of its header. That's not
>>> the usual way it's done, but I don't know C++ well enough to know
>>> if it matters. Nevertheless, I'd try
>>>
>>>  extern "C" {
>>>     void R_init_bgx(DllInfo *info) {
>>>       R_registerRoutines(info, cMethods,NULL,NULL,NULL);
>>>     }
>>>  }
>>>
>>> just to see if it helps.
>>>
>>> Duncan Murdoch
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>

-- 
Brian D. Ripley,                  ripley at stats.ox.ac.uk
Professor of Applied Statistics,  http://www.stats.ox.ac.uk/~ripley/
University of Oxford,             Tel:  +44 1865 272861 (self)
1 South Parks Road,                     +44 1865 272866 (PA)
Oxford OX1 3TG, UK                Fax:  +44 1865 272595



[Rd] Rinternals.h and undefined symbols
Prof Brian Ripley