Using SWIG to build C++ extension

Bas Michielsen B.L.Michielsen at wanadoo.fr
Fri Jul 11 19:25:00 EDT 2008


mk wrote:

> Hello,
> 
> I'm having terrible problems building C++ extension to Python 2.4 using
> SWIG. I'd appreciate if somebody knowledgeable at the subject took a
> look at it. swig-1.3.29, g++ (GCC) 4.1.1 20070105 (Red Hat 4.1.1-52).
> 
> I used following commands to build C++ extension:
> 
> # swig -c++ -python edit_distance.i
> # c++ -c edit_distance.c edit_distance_wrap.cxx edit_distance.cpp -I.
> -I/usr/include/python2.4
> 
> 
> Linux RH (9.156.44.105) root ~/tmp # c++ -c edit_distance.c
> edit_distance_wrap.cxx edit_distance.cpp -I. -I/usr/include/python2.4
> c++: edit_distance.cpp: No such file or directory
> edit_distance_wrap.cxx: In function ‘PyObject*
> _wrap_edit_distance(PyObject*, PyObject*)’:
> edit_distance_wrap.cxx:2579: error: ‘string’ was not declared in this
> scope edit_distance_wrap.cxx:2579: error: ‘arg1’ was not declared in this
> scope edit_distance_wrap.cxx:2580: error: ‘arg2’ was not declared in this
> scope edit_distance_wrap.cxx:2597: error: expected type-specifier before
> ‘string’ edit_distance_wrap.cxx:2597: error: expected `>' before ‘string’
> edit_distance_wrap.cxx:2597: error: expected `(' before ‘string’
> edit_distance_wrap.cxx:2597: error: expected primary-expression before
> ‘>’ token
> edit_distance_wrap.cxx:2597: error: expected `)' before ‘;’ token
> edit_distance_wrap.cxx:2605: error: expected type-specifier before
> ‘string’ edit_distance_wrap.cxx:2605: error: expected `>' before ‘string’
> edit_distance_wrap.cxx:2605: error: expected `(' before ‘string’
> edit_distance_wrap.cxx:2605: error: expected primary-expression before
> ‘>’ token
> edit_distance_wrap.cxx:2605: error: expected `)' before ‘;’ token
> 
> What's weird is that I _did_ use std:: namespace prefix carefully in the
> code:
> 
> #include <string>
> #include <vector>
> #include <iostream>
> 
>   const unsigned int cost_del = 1;
>   const unsigned int cost_ins = 1;
>   const unsigned int cost_sub = 1;
> 
> 
>   unsigned int edit_distance( std::string& s1, std::string& s2 )
>   {
>          const size_t len1 = s1.length(), len2 = s2.length();
>          std::vector<std::vector<unsigned int> > d(len1 + 1,
> std::vector<unsigned int>(len2 + 1));
> 
>          for(int i = 1; i <= len1; ++i)
>                  for(int j = 1; j <= len2; ++j)
>                          d[i][j] = std::min(d[i - 1][j] + 1,
> std::min(d[i][j - 1] + 1, d[i - 1][j - 1] + (s1[i - 1] == s2[j - 1] ? 0
> : 1)));
> 
>          return d[len1][len2];
> }
> 
> Ok, anyway I fixed it in the generated code (edit_distance_wrap.cxx). It
> compiled to .o file fine then. It linked to _edit_distance.so as well:
> 
> # c++ -shared edit_distance_wrap.o -o _edit_distance.so
> 
> But now I get import error in Python!
> 
> Linux RH root ~/tmp # python
> Python 2.4.3 (#1, Dec 11 2006, 11:38:52)
> [GCC 4.1.1 20061130 (Red Hat 4.1.1-43)] on linux2
> Type "help", "copyright", "credits" or "license" for more information.
>  >>> import edit_distance
> Traceback (most recent call last):
>    File "<stdin>", line 1, in ?
>    File "edit_distance.py", line 5, in ?
>      import _edit_distance
> ImportError: ./_edit_distance.so: undefined symbol: _Z13edit_distanceRSsS_
> 
> 
> 
> What did I do to deserve this? :-)
> 
> 
> edit_distance.i file just in case:
> 
> %module edit_distance
> %{
> #include "edit_distance.h"
> %}
> 
> extern unsigned int edit_distance(string& s1, string& s2);

Hello, 

I took your example files and did the following:
changed the #include "edit_distance.h" to #include "edit_distance.c"
in the edit_distance.i file. 
Then I changed the first few lines of your function definition
unsigned int edit_distance( const char* c1, const char* c2 )
  {
    std::string s1( c1), s2( c2);
and also adapted the signature in the edit_distance.i file.
Then
swig -shadow -c++ -python edit_distance.i
g++ -c -fpic  -I/usr/include/python edit_distance_wrap.cxx
g++ -shared edit_distance_wrap.o -o _edit_distance.so

I could import edit_distance without any error messages
>>> import edit_distance
>>> print edit_distance.edit_distance( "toto", "titi")
2
>>> print edit_distance.edit_distance( "toto", "toti")
1

Perhaps I changed too many things, but this may get you started, 

Regards, 

Bas



More information about the Python-list mailing list