Hi Jens,<div><br></div><div>I want to thank you very much for all your help and especially your patience.</div><div><br></div><div>Everything is working perfectly now.</div><div><br></div><div>I apologize for the mixed up code...far too much C and not enough C++ in combination with the old adage "Haste makes waste" !!!</div>
<div><br></div><div>Happy New Year Jens.</div><div><br></div><div>         Gary ---</div><div><br></div><div><br></div><div><br><br><div class="gmail_quote">On Sun, Jan 22, 2012 at 1:20 PM, Jens Thoms Toerring <span dir="ltr"><<a href="mailto:jt@toerring.de">jt@toerring.de</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Gary,<br>
<div class="im"><br>
On Sun, Jan 22, 2012 at 11:57:44AM -0500, Gary Fisher wrote:<br>
>         >>> What does "return (static char *)Null" mean?<br>
><br>
> My mistake...I meant "return (const char *)Null" ... not static....and yes<br>
> I do believe NULL is used in C++.  At least the compiler didn't witch at me<br>
> for it.<br>
<br>
</div>There's still no reason for the cast. And while you use 'NULL'<br>
in C quite often it's frowned upon in C++. All you really need<br>
is<br>
<br>
     return 0;<br>
<br>
Since the compiler knows that the function returns a 'const char *'<br>
it will automatically do the conversion. By casting (and then<br>
even using a C-style cast, which is strongly discouraged in C++)<br>
you tell the compiler "I know better than you" and you shouldn't<br>
do that unless there's something the compiler can't figure out<br>
on his own since a) you keep the compiler from explaining about<br>
stuff that shouldn't/can't be done (don't see compiler complaints<br>
as a nuisance but as a valuable help you to write correct pro-<br>
grams) and b) you make the next person reading your code wonder<br>
what this is all about.<br>
<div class="im"><br>
> When I use "nm -C libword.so" on my little wrapped library I see nothing in<br>
> the output to suggest a "word" class or a "reverse" method.<br>
<br>
</div>And that's at the very heart of your problem: the symbols needed<br>
by the wrapper script don't exist in 'libword.so'. Rhe reason is<br>
that there's not the slightest bit of necessity for the compiler/<br>
linker to put them in there: you have a class declared with in-<br>
lined methods that is never used anywhere. So there's no reason<br>
to use the class for anything and it simply gets thrown out.<br>
<br>
Every program using your library would include a header file for<br>
the library that defines the interface. And while doing so it<br>
would see the declaration of the class and would construct it's<br>
own version of the class when it's needed.<br>
<br>
I'm a bit at a loss at understanding how you got your SIP wrapper<br>
to work without a header file, but that's another topic;-)<br>
<br>
The quick fix is to simply splitting the word.cpp file up into<br>
two parts, the necessary header file with the class declaration<br>
and a cpp file with the function definitions. I.e. something<br>
like this:<br>
<br>
------- word.hpp -----------------------------<br>
#ifndef WORD_HPP_<br>
#define WORD_HPP_<br>
<br>
class Word {<br>
  public:<br>
<br>
    Word( const char * w );<br>
<br>
    const char * reverse( );<br>
<br>
  private:<br>
<br>
    const char * the_word;<br>
};<br>
<br>
#endif<br>
------- word.cpp -----------------------------<br>
#include "word.hpp"<br>
<br>
Word::Word( const char * w ) :<br>
    the_word( w )<br>
{ }<br>
<br>
const char *<br>
Word::reverse( )<br>
{<br>
   return 0;<br>
}<br>
----------------------------------------------<br>
<br>
BTW: don't forget the 'public:' in the class!<br>
<br>
If you now compile this into a shared library it will con-<br>
tain both the symbols for the constructor and the reverse()<br>
method. And within the SIP wrapper you include the 'word.hpp'<br>
header file.<br>
<div class="im"><br>
  However, when<br>
> I run "nm -C word.so" against the library generated by make I get things<br>
> like:<br>
><br>
> 000021b4 d methods_Word<br>
>          U Word::Word(char const*)<br>
>          U Word::reverse() const<br>
><br>
> among other things.<br>
<br>
</div>Yes, the 'word.so' library needs those symbols and expects<br>
them in one of the libraries it was linked with, but they<br>
aren't anywhere. That will be only noticed when Python tries<br>
to load the 'word.so' library and thus it fails.<br>
<br>
BTW, the code in your program looks a bit broken.<br>
<br>
> class Word {<br>
>   const char *the_word;<br>
>   //  const char *the_reverse;<br>
>   char buffer[20], *pb;<br>
><br>
>   int i, len;<br>
><br>
>   Word( const char *w) {<br>
>       the_word = w;<br>
>   }<br>
<br>
Do you realize that 'the_word' is now set to some memory<br>
that doesn't belong to this class? It looks as if you<br>
would like to store a word using this class, but that's<br>
not what you do - all you keep is a pointer to some<br>
string somewhere else in memory (and not owned by the<br>
class instance). And if this memory is used for something<br>
else then the 'the_word' pointer will point to memory that<br>
doesn't contain a string anymore. I guess you're coming from<br>
languages where memory allocation is done for you in the<br>
background (like in Python), but if you write in C++ (or C)<br>
you will have to be very careful to do the right thing with<br>
memory, e.g. just holding a pointer to some memory doesn't<br>
make it "yours" - you have to ensure that nothing else will<br>
fiddle with the memory pointed to.<br>
<br>
>   const char *reverse () {<br>
><br>
>       return (const char *) NULL;<br>
><br>
>       /************************<br>
>       len = strlen(the_word);<br>
>       strcpy (buffer, the_word);<br>
<br>
What happens if what 'the_word' points to is longer than 19<br>
chars? You write past the end of buffer with unforseeable<br>
effects. In the worst case it even might seem to work at<br>
firt until some strange and hard to trace erros show up<br>
much later...<br>
<br>
>       pb = (char *)the_word;<br>
<br>
That's exactly one of the places were a cast shouldn't be<br>
used. 'the_word' points to memory you are not allowed to<br>
change. And to get around this you need the cast. So you're<br>
now operating directly on the memory where your word is<br>
stored which could reside in read-only memory.<br>
<br>
>       for (i=len-1 ; i>=0 ; i--) {<br>
>         *pb = buffer[i];<br>
>         pb++;<br>
>       }<br>
<br>
>       *pb = '\0';<br>
><br>
>       return the_word;<br>
>   }<br>
> };<br>
<br>
Here's some way you could do it (but note, I didn't carefully<br>
check everything):<br>
<br>
------- word.hpp -----------------------------<br>
#ifndef WORD_HPP_<br>
#define WORD_HPP_<br>
<br>
#include <cstring><br>
<br>
class Word {<br>
  public:<br>
<br>
    Word( const char * w );<br>
<br>
        ~Word( );<br>
<br>
    const char * reverse( );<br>
<br>
  private:<br>
<br>
    char * the_word;<br>
};<br>
<br>
#endif<br>
------- word.cpp -----------------------------<br>
#include "word.hpp"<br>
<br>
Word::Word( const char * w )<br>
{<br>
    the_word = new char [ ( w != 0 ? strlen( w ) : 0 ) + 1 ];<br>
<br>
    if ( w != 0 )<br>
        strcpy( the_word, w );<br>
    else<br>
        *the_word = '\0';<br>
}<br>
<br>
Word::~Word( )<br>
{<br>
    delete [ ] the_word;<br>
}<br>
<br>
const char *<br>
Word::reverse( )<br>
{<br>
    char *ps = the_word,<br>
         *pe = the_word + strlen( the_word );<br>
<br>
    while ( ps < pe )<br>
    {<br>
        char tmp = *ps;<br>
        *ps++ = *pe;<br>
        *pe-- = tmp;<br>
    }<br>
<br>
    return the_word;<br>
}<br>
----------------------------------------------<br>
<br>
But since you write C++ it is probably nuch more reasonable<br>
(and safer) to use the std::string class instead of creating<br>
a probably inferior and slower version on your own;-) And all<br>
this is very C-ish, for example in C++ you would rather return<br>
a Word instance from the reverse() method instead of a pointer<br>
to something in the innards of the class...<br>
<div class="HOEnZb"><div class="h5"><br>
                            Regards, Jens<br>
--<br>
  \   Jens Thoms Toerring  ________      <a href="mailto:jt@toerring.de">jt@toerring.de</a><br>
   \_______________________________      <a href="http://toerring.de" target="_blank">http://toerring.de</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div>--------------------------------------------------------------------------------------------------</div><div><span style="font-family:Arial,sans-serif"><br>
</span></div><div>
        
        
        


<p style="margin-top:0.19in;margin-bottom:0.19in;background:#ffffff">
<font color="#333333">“<font face="Arial, sans-serif"><font>Nothing
in all the world is more dangerous than sincere ignorance </font></font></font><span style="font-family:Arial,sans-serif;color:rgb(51,51,51)">and
conscientious stupidity.”</span></p>
<p style="margin-top:0.19in;margin-bottom:0.19in;background:#ffffff">
<font face="Arial, sans-serif"><font>     ~ Martin Luther King, Jr</font></font></p></div><div><p></p></div><font size="3" face="Times New Roman">



</font><br>
</div>