11

I want to start learning more about using SWIG and other methods to interface Python and C++. To get started, I wanted to compile this simple program mentioned in another post:

#include <Python.h> 

 int main() 
 { 
      Py_Initialize(); 
      PyRun_SimpleString ("import sys; sys.path.insert(0, '/home/ely/Desktop/Python/C-Python/')");

      PyObject* pModule = NULL; 
      PyObject* pFunc   = NULL; 

      pModule = PyImport_ImportModule("hello");
      if(pModule == NULL){
           printf("Error importing module.");
           exit(-1);
      }


      pFunc   = PyObject_GetAttrString(pModule, "Hello"); 
      PyEval_CallObject(pFunc, NULL); 
      Py_Finalize(); 
      return 0; 
 }

where the file "hello.py" just has the contents:

 def Hello():
     print "Hello world!"

Note: I already have python2.7-dev and python-dev and libboost-python-dev installed. But when I go to compile the code, I get errors that I believe are due to incorrectly linking to the Python libraries.

 ely@AMDESK:~/Desktop/Python/C-Python$ gcc -I/usr/include/python2.7 test.cpp    /tmp/ccVnzwDp.o: In function `main':
 test.cpp:(.text+0x9): undefined reference to `Py_Initialize'
 test.cpp:(.text+0x23): undefined reference to `PyImport_ImportModule'
 test.cpp:(.text+0x58): undefined reference to `PyObject_GetAttrString'
 test.cpp:(.text+0x72): undefined reference to `PyEval_CallObjectWithKeywords'
 test.cpp:(.text+0x77): undefined reference to `Py_Finalize'
 /tmp/ccVnzwDp.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0'
 collect2: ld returned 1 exit status

I was fishing around for examples of this online, and I found the following syntax, which causes the code to compile into an object file, but then I am unable to actually execute the file.

 ely@AMDESK:~/Desktop/Python/C-Python$ gcc -c -g -I/usr/include/python2.7 test.cpp 
 ely@AMDESK:~/Desktop/Python/C-Python$ ./test.o
 bash: ./test.o: Permission denied
 ely@AMDESK:~/Desktop/Python/C-Python$ chmod ug=rx ./test.o
 ely@AMDESK:~/Desktop/Python/C-Python$ ./test.o
 bash: ./test.o: cannot execute binary file
 ely@AMDESK:~/Desktop/Python/C-Python$ sudo chmod ug=rx ./test.o
 ely@AMDESK:~/Desktop/Python/C-Python$ ./test.o
 bash: ./test.o: cannot execute binary file

The same behavior as above is still seen if I use g++ instead of gcc.

Help in understanding my error in linking would be great, and even better for any sort of explanation that helps me understand the "logic" behind the kind of linking I need to do, so that I'll remember better what possible things I am forgetting the next time. Thanks!

Community
  • 1
  • 1
ely
  • 74,674
  • 34
  • 147
  • 228
  • 1
    Another remark: you cannot execute `.o` files directly. First you need to link them into an `ELF` executable. – ulidtko Mar 22 '12 at 16:47

3 Answers3

12

What you are seeing are linker errors. To fix those, you need to link python2.7 library.

Try next line :

gcc -I/usr/include/python2.7 test.c -lpython2.7

it should work.

BЈовић
  • 62,405
  • 41
  • 173
  • 273
  • 1
    What is `kel.cpp`? Should that be replaced with my example file `test.cpp`? If so, then I still get an error: `ely@AMDESK:~/Desktop/Python/C-Python$ gcc -I/usr/include/python2.7 test.cpp -lpython2.7` gives the error: `/tmp/ccaahL1m.o:(.eh_frame+0x12): undefined reference to `__gxx_personality_v0' collect2: ld returned 1 exit status` – ely Mar 22 '12 at 16:38
  • @EMS I named the file kel.cpp. Fixed in the edit. That is weird that you get an error. Which distro are you using? – BЈовић Mar 22 '12 at 16:42
  • 2
    @EMS, compile with `g++` not `gcc`. – Winston Ewert Mar 22 '12 at 16:43
  • I'm on Ubuntu 11.04, gcc version is: (Ubuntu/Linaro 4.4.5-15ubuntu1) 4.4.5 – ely Mar 22 '12 at 16:43
  • 1
    It compiles and links fine using gcc 4.6.1 on fedora 15. – BЈовић Mar 22 '12 at 16:45
  • 1
    Yes, with g++ it worked. I also had to make a slight correction to the c++ code, because I had to give it the path to the Python module. Now it works. – ely Mar 22 '12 at 16:47
  • If I may ask: how should you do when compiling a constructor file ? That is, test.c is the constructor for a header file but with Python calls in it ? Because -lpython2.7 needs a reference to main apparently. I am allowing myself to ask this here as the answer is strongly related to a question on which my project is blocked. (I have also asked a question here btw https://stackoverflow.com/questions/64182421/linking-c-object-files-embedded-with-python) – Joachim Oct 03 '20 at 09:06
2

First, do you compile C or C++ code?

Use gcc for the former, and g++ for the latter. C++ code needs some additional linking to be performed.

Second: you have to link your program to libpython2.7.so to embed the interpreter into it. To do this, add -lpython2.7 to gcc command line.

ulidtko
  • 14,740
  • 10
  • 56
  • 88
1

test.o is not your executable file, that's why you can't execute it.

The default name for your program is a.out, try running that. You can specify a name for your program using the -o option.

Winston Ewert
  • 44,070
  • 10
  • 68
  • 83