Embedding Python in C - Cross-platform Development

Embedding Python code into C Linux vs Windows techniques.

Sometimes it's handy to spawn a Python shell from within C programs, or to manipulate Python objects easily from there. Here is a way to embed Python code into C code and have it compile into a native binary (or as a library). The only requirements or course are a working Python 2.x or 3.x installation.

Cross-platform Python Embedding tutorial

Create a test file, embed.c

#include <Python.h>

int main(int argc, char *argv[])
{
    Py_SetProgramName(argv[0]);  /* optional but recommended */
    Py_Initialize();
    PyRun_SimpleString("from time import time,ctime\n"
        "print('Today is', ctime(time()))\n");
    Py_Finalize();
    return 0;
}

Compile & test on Linux x86_64

gcc embed.c $(python-config --cflags --libs) -o embed
./embed
('Today is', 'Tue Jan 27 09:30:30 2015')

Compile & test on Windows64 (or wine). Get our python.exe-config

mingw64-env
$CC embed.c $(wine python C:\\Python27\\python.exe-config --cflags --libs) -o embed.exe
./embed.exe
('Today is', 'Tue Jan 27 09:30:30 2015')

on fail

Cannot find python.exe-config? We made that up to fool Makefiles that embed Python (and make them work with cross-compiling). Name it python.exe-config and put it somewhere in wine's PYTHONPATH. Now such Makefiles should start working.

#!C:\\Python27\python.exe
import sys, subprocess

class ww(object):
    def __init__(self, argv):
        try:
            argv[1]
        except IndexError:
            pass
        else:
            try:
                p=subprocess.check_output(["winepath","c:\\Python27"]).strip()
                q = '/usr/x86_64-w64-mingw32/sys-root/mingw'
            except OSError:
                p = '/c/Python27'
        for x in argv:
            if x == '--includes':
                sys.stdout.write('-I'+p+'/include')
            # change this
            if x == '--prefix' or x == '--exec-prefix':
                sys.stdout.write(' '+p+'/usr')
            if x == '--cflags':
                sys.stdout.write(' -I'+p+'/include -I'+q+'/include -D_WIN32_WINNT=0x0501 -DWINVER=0x0501 -DG_OS_WIN32')
            if x == '--libs':
                sys.stdout.write(' -lpthread -mthreads -lm -lpython27 -L'+p+'/libs -L'+q+'/libs')
            if x == '--ldflags':
                sys.stdout.write(' -lpthread -mthreads -lm -lpython27 -L'+p+'/Python27/libs -L'+q+'/libs -Xlinker -export-dynamic')

if __name__ == "__main__":
    app = ww(sys.argv)

Incompatible libpython27?

ld: skipping incompatible libpython27.a when searching for -lpython27
python27.lib: error adding symbols: File in wrong format

Rebuild Python 2.7's linkable library to a usable format.

cd ~/.wine/drive_c
gendef windows/system32/python27.dll
/usr/bin/x86_64-w64-mingw32-dlltool -D python27.dll -d python27.def -l libpython27.a

References

Link to Python with MinGW

Embed Python into a Windows application


CCBY Copyright © 2016 Henry Kroll III, thenerdshow.com This web page is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.