This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Embedding Python: undefined reference to `_imp__Py_Initialize'
(2 answers)
Closed 1 year ago.
I'm having trouble importing Python.h to a C program.
I have 4 files, hellofunc.c, hellomake.c, hellomake.h and Makefile.
The hellomake.h, Python.h and all related Python files are in a include folder.
And the rest is in the program folder.
├───include
│ ├───cpython
│ └───internal
├───lib
└───program
The code of hellofunc.c file is:
#include <stdio.h>
#include <hellomake.h>
void myPrintHelloMake(void) {
printf("Hello makefiles!\n");
return;
}
The code of hellomake.h is:
void myPrintHelloMake(void);
The code of hellomake.c is:
#include <conio.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <windows.h>
#include <Python.h>
#include <hellomake.h>
int main() {
// call a function in another file
myPrintHelloMake();
Py_Initialize();
PyRun_SimpleString("print('Hello World from Embedded Python!!!')");
Py_Finalize();
return(0);
}
The code of Makefile is:
IDIR =../include
CC=gcc
CFLAGS=-I$(IDIR)
ODIR=obj
LDIR =../lib
LIBS=-lm
_DEPS = hellomake.h
DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
_OBJ = hellomake.o hellofunc.o
OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
$(ODIR)/%.o: %.c $(DEPS)
$(CC) -c -o $# $< $(CFLAGS)
hellomake: $(_OBJ)
$(CC) -o $# $^ $(CFLAGS) $(LIBS)
.PHONY: clean
clean:
rm -f *.o *~ core $(INCDIR)/*~
The error that I got is:
gcc -o hellomake hellomake.o hellofunc.o -I../include -lm
hellomake.o:hellomake.c:(.text+0x14): undefined reference to `_imp__Py_Initialize'
hellomake.o:hellomake.c:(.text+0x2a): undefined reference to `_imp__PyRun_SimpleStringFlags'
hellomake.o:hellomake.c:(.text+0x31): undefined reference to `_imp__Py_Finalize'
collect2.exe: error: ld returned 1 exit status
make: *** [Makefile:56: hellomake] Error 1
Related
I have a .cpp (called trial.cpp) file as follows:
#include "trial.hpp"
int main()
{
cout << "hello";
return 0;
}
My header file (trial.hpp) is:
#include <iostream>
using namespace std;
I have a .i file (trial.i) as follows:
%module trial
%{
#include "trial.hpp"
%}
%include trial.hpp
I have used SWIG in the following manner in cmd to generate .pyd, .py, .o and .cxx files:
swig -c++ -python trial.i
g++ -c trial_wrap.cxx -I C:\Users.....Python\Python37\include
g++ -shared trial_wrap.o -o _trial.pyd -L
C:\Users.....\Python\Python37\libs -l
python37
The files are generated successfully
However when I open Python command prompt and run this:
from trial import *
main()
I get an error saying
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'main' is not defined
How can I resolve this issue?
Moreover, if I'm using another function name (say fn1()) instead of main(), I get the following error in the third command:
g++ -shared trial_wrap.o -o _trial.pyd -L
C:\Users.....\Python\Python37\libs -l python37
The error is:
undefined reference to fn1()
I'd like to use fn1() instead of main()
How can I solve this issue?
Fixed it!
Used these three statements instead:
swig -c++ -python trial.i
g++ -c trial_wrap.cxx trial.cpp -I C:\Users\ngoyal\AppData\Local\Programs\Python\Python37\include
g++ -shared -o _trial.pyd trial.o trial_wrap.o -L C:\Users\ngoyal\AppData\Local\Programs\Python\Python37\libs -l python37
Also had to change main() to a non reserved function name and gave the function definition in the header file.
Is there a good way to embed both a Python2 and a Python3 interpreter into a C program and then running either one or the other with the decision occurring at runtime?
Here's an example attempt:
Makefile:
all: main
main: main.c librun_in_py2.so librun_in_py3.so
g++ main.c -lrun_in_py2 -lrun_in_py3 -L. -Wl,-rpath -Wl,$$ORIGIN -o main
librun_in_py2.so: run_in_py2.c
g++ $$(python2.7-config --cflags --ldflags) -shared -fPIC $< -o $#
librun_in_py3.so: run_in_py3.c
g++ $$(python3.4-config --cflags --ldflags) -shared -fPIC $< -o $#
clean:
#-rm main *.so
main.c
void run_in_py2(const char* const str);
void run_in_py3(const char* const str);
static const char str2[] = "from time import time,ctime\n"
"import sys\n"
"print sys.version_info\n"
"print 'Today is',ctime(time())\n";
static const char str3[] = "from time import time,ctime\n"
"import sys\n"
"print(sys.version_info)\n"
"print('Today is', ctime(time()))\n";
int main(int argc, char* [])
{
if (argc == 2)
run_in_py2(str2);
else
run_in_py3(str3);
}
run_in_py2.c
#include <Python.h>
void run_in_py2(const char* const str)
{
Py_Initialize();
PyRun_SimpleString(str);
Py_Finalize();
}
run_in_py3.c:
#include <Python.h>
void run_in_py3(const char* const str)
{
Py_Initialize();
PyRun_SimpleString(str);
Py_Finalize();
}
Because of the order of library linking the result is always the same:
$ ./main
sys.version_info(major=2, minor=7, micro=9, releaselevel='final', serial=0)
('Today is', 'Thu Jun 4 10:59:29 2015')
Since the names are the same it looks like the linker resolves everything with the Python 2 interpreter. Is there some way to isolate the names or to encourage the linker to be lazier in resolving them? If possible, it'd be ideal to get the linker to confirm that all names can be resolved and but put off symbol resolution until the appropriate linker can be chosen.
A highly related question asks about running two independent embedded interpreters at the same time:
Multiple independent embedded Python Interpreters on multiple operating system threads invoked from C/C++ program
The suggestion there is to use two separate processes but I suspect there's a simpler answer to this question.
The reason behind the question is that I thought I understood from a conversation with someone way back when that there was a program that did this. And now I'm just curious about how it would be done.
I'm trying to embedding some Python code into C; It's the first time I do a thing like that.
Here is the simple code of my first attempt copied by a guide on internet:
#include <Python.h>
void exec_pycode(const char* code)
{
Py_Initialize();
PyRun_SimpleString(code);
Py_Finalize();
}
int main(int argc, char **argv) {
exec_pycode(argv[1]);
return 0;
}
So I've installed python3.4-dev package.
Then for having info for the linker I typed:
pkg-config --cflags --libs python3
Then I tried to compile my code:
gcc -std=c99 -o main -I /usr/local/include/python3.4m -L /usr/local/lib -lpython3.4m main.c
(according the command before)
but this is the result:
/tmp/ccJFmdcr.o: in function "exec_pycode":
main.c:(.text+0xd): reference undefined to "Py_Initialize"
main.c:(.text+0x1e): reference undefined to "PyRun_SimpleStringFlags"
main.c:(.text+0x23): reference undefined to "Py_Finalize"
collect2: error: ld returned 1 exit status
It would seem that there is a problem with linking phase, but I can't understend where is the problem seeing that i've passed to the linker the exact paths of the header and of the library. How can I solve that problem?
Try reordering your compilation command, such that all linking options are specified after your C source files:
gcc -std=c99 -o main -I /usr/local/include/python3.4m main.c \
-L /usr/local/lib -lpython3.4m
I have written a Python API in C code and saved the file as foo.c.
Code:
#include <Python.h>
#include <stdio.h>
static PyObject *foo_add(PyObject *self, PyObject *args)
{
int a;
int b;
if (!PyArg_ParseTuple(args, "ii", &a, &b))
{
return NULL;
}
return Py_BuildValue("i", a + b);
}
static PyMethodDef foo_methods[] = {
{ "add", (PyCFunction)foo_add, METH_VARARGS, NULL },
{ NULL, NULL, 0, NULL }
};
PyMODINIT_FUNC initfoo()
{
Py_InitModule3("foo", foo_methods, "My first extension module.");
}
When i try to compile using the below mentioned command i am getting compilation error.
Command: gcc -shared -I/usr/include/python2.7 foo.c -o foo.so
Error:
gcc -shared -I/usr/include/python2.7 foo.c -o foo.so
/usr/bin/ld: /tmp/ccd6XiZp.o: relocation R_X86_64_32 against `.rodata' can not be used when making a shared object; recompile with -fPIC
/tmp/ccd6XiZp.o: error adding symbols: Bad value
collect2: error: ld returned 1 exit status
If i give compilation command with "-c" option, its getting compiled successfully and created the object file foo.so (This is the executable file).
I have to create a object file (without using -c option in compilation command) and import them in Python shell to verify it.
Please let me know what am i doing wrong here.
In your compilation flags you should include -fPIC to compile as position independent code. This is required for dynamically linked libraries.
e.g.
gcc -c -fPIC foo.c -o foo.o
gcc -shared foo.o -o foo
or in a single step
gcc -shared -fPIC foo.c -o foo.so
I want to use a c program invoke a python program,
os:ubuntu 12.10 x64
python2.7.3
C code:
#include <stdio.h>
#include <stdlib.h>
#include <python2.7/Python.h>
int main(int argc, char** argv)
{
printf("Hello world!\n");
Py_Initialize();
Py_SetProgramName("c_python");
PyRun_SimpleString("print \"Hello world,Python!\"\n");
Py_Finalize();
exit(0);
}
compile shell:
gcc -I/usr/include/python2.7 -L/usr/lib/python2.7 -Wall -fPIC c_python.c -o c_pyton
/tmp/cciuHgrf.o:in ‘main’:
c_python.c:(.text+0x1c):reference undefined ‘Py_Initialize’
c_python.c:(.text+0x28):reference undefined ‘Py_SetProgramName’
c_python.c:(.text+0x3e):reference undefined ‘Py_Finalize’
collect2: error: ld return 1
You need to link the Python interpreter into your executable: -lpython.