I knocked the bastard off:

extern "C" {
struct __gmp_alloc_cstring_c
{
   void (*free_func) (void *, size_t);
};
}

struct __gmp_alloc_cstring : __gmp_alloc_cstring_c
{
  char *str;
  __gmp_alloc_cstring(char *s) { str = s; }
  ~__gmp_alloc_cstring()
  {
    mp_get_memory_functions (NULL, NULL, &free_func);
    (*free_func) (str, std::strlen(str)+1);
  }
};

Basically I declare a C struct which makes the function pointer a
pointer to a C function. Then I inherit that C struct in the C++
struct.

MPIR now builds and passes make check with --enable-cxx with the Sun
CC compiler. Technically the Sun compiler is correct to complain.
Let's hope it still compiles with GCC!

Bill.

2009/1/10 Bill Hart <goodwillh...@googlemail.com>:
> Unfortunately that doesn't seem to change the interface of freefunc.
> The problem seems to be that you can only change the interface of
> functions at file level, and freefunc is not at file level. But
> putting it at file level would make it unthreadsafe.
>
> Bill.
>
> 2009/1/10 user923005 <dcor...@connx.com>:
>>
>> On Jan 9, 8:47 pm, Bill Hart <goodwillh...@googlemail.com> wrote:
>>> I've been working on getting MPIR to compile on Sun CC with --enable-
>>> cxx. I've fixed the attribute errors by only defining ATTRIBUTE_* when
>>> __GNUC__ is defined. This fixes lots of build warnings actually,
>>> though if __GNUC__ is not defined for a compiler which supports
>>> attributes, then MPIR could potentially be slightly slower (probably
>>> infinitesimally).
>>>
>>> But I'm stuck with the following:
>>>
>>> /* this is much the same as gmp_allocated_string in gmp-impl.h
>>>    since gmp-impl.h is not publicly available, I redefine it here
>>>    I use a different name to avoid possible clashes */
>>> struct __gmp_alloc_cstring
>>> {
>>>   char *str;
>>>   __gmp_alloc_cstring(char *s) { str = s; }
>>>   ~__gmp_alloc_cstring()
>>>   {
>>>     void (*freefunc) (void *, size_t);
>>>     mp_get_memory_functions (NULL, NULL, &freefunc);
>>>     (*freefunc) (str, std::strlen(str)+1);
>>>   }
>>>
>>> };
>>>
>>> The Sun CC compiler says:
>>>
>>> "../../gmpxx.h", line 1303: Error: Formal argument 3 of type extern
>>> "C" void(*)(void*,unsigned long)* in call to __gmp_get_memory_functions
>>> (extern "C" void*(*)(unsigned long)*, extern "C" void*(*)
>>> (void*,unsigned long,unsigned long)*, extern "C" void(*)
>>> (void*,unsigned long)*) is being passed void(*)(void*,unsigned long)*.
>>> "../../gmpxx.h", line 1304: Warning: The variable freefunc has not yet
>>> been assigned a value.
>>>
>>> It took me a while to figure out what the code is trying to do.
>>> Basically __gmp_free_func is the default function for freeing memory
>>> allocated by GMP internally. But the user can actually define their
>>> own memory management functions if they want. There's an interface for
>>> that, and GMP stores function pointers for the memory managment
>>> functions the user specifies.
>>>
>>> Now if you want to free space allocated by the current memory
>>> management function, then you better not call __gmp_free_func, as the
>>> user may have replaced it as the current memory management function.
>>> Instead you want to call the function the user defined for this
>>> purpose. So you need to retrieve the function pointer GMP has stored
>>> for this user defined deallocation function.
>>>
>>> That's what the function mp_get_memory_functions does. If you pass it
>>> a reference to a function pointer as the third argument, it will set
>>> that function pointer to point to the user defined deallocation
>>> function.
>>>
>>> So in the destructor for this struct, it first declares a function
>>> pointer, called freefunc. Then it calls mp_get_memory_functions with a
>>> reference to freefunc as its third argument, and this sets that
>>> function pointer to be the user defined allocation function. Then it
>>> actually calls this deallocation function to deallocate the space
>>> allocated by the initialiser for the struct.
>>>
>>> Now the problem is, for some stupid reason, the sun CC thinks
>>> mp_get_memory_functions doesn't take a reference to a function
>>> pointer, but a reference to an extern "C" function pointer. I've no
>>> idea where it gets that from. The function mp_get_memory_functions is
>>> defines in mp_get_gns.c and its prototype is actually:
>>>
>>> void
>>> mp_get_memory_functions (void *(**alloc_func) (size_t),
>>>                          void *(**realloc_func) (void *, size_t, size_t),
>>>                          void (**free_func) (void *, size_t))
>>>
>>> Does anyone see how to fix this problem?
>>>
>>> I'm stumped.
>>
>> Have you tried putting
>>
>> #ifdef __cplusplus
>> extern "C" {
>> #endif
>> /*
>> Code goes here...
>> */
>> #ifdef __cplusplus
>> }
>> #endif
>>
>> Around both the declarations in the header file and also around the C
>> code?
>>
>> I am only guessing, but a problem can arise if only one set has extern
>> "C" changing the interface.
>>
>> To be really sure I would have to examine the code carefully.
>>
>> For example, consider:
>>
>> /* someheader.h: */
>> #ifdef __cplusplus
>> extern "C" double myfunc(double);
>> #endif
>>
>> ...
>>
>> /* somefile.c: */
>> #include "someheader.h"
>> double myfunc(double d)
>> {
>>  return sin(d) * sqrt(d);
>> }
>>
>> Now, since the function definition is not actually bracketed with
>> extern "C" like the declaration is, then the implementation file will
>> have a name mangled object and we won't find it if we reference it
>> using the header file.
>>
>>
>> >>
>>
>

--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"mpir-devel" group.
To post to this group, send email to mpir-devel@googlegroups.com
To unsubscribe from this group, send email to 
mpir-devel+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/mpir-devel?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to